std::array 默认初始化还是值初始化?

Posted

技术标签:

【中文标题】std::array 默认初始化还是值初始化?【英文标题】:Does std::array default-initialize or value-initialize? 【发布时间】:2015-07-02 10:03:19 【问题描述】:

根据cppreference,std::array 的构造函数在创建std::array 时执行默认初始化。但是,当我在 Visual Studio 12.0 中进行一些测试时,在某些情况下 std::array 似乎正在执行值初始化。

std::array<int, 3> arr1;  // gives me some garbage values, as expected
auto arr2 = std::array<int, 3>();  // gives me three 0, value-initialize?

另外,当std::array 是一个类的成员时,有时它的值不确定,而有时它全为零。

class Container 
public:
    Container() ...

    int& operator[](size_t i)  return arr[i];     
    size_t size()  return ARR_SIZE; 

private:
    static const size_t ARR_SIZE = 3;
    std::array<int, ARR_SIZE> arr;
;

当构造函数没有显式定义或者arr不在成员初始化列表中时,arr包含不确定的值。

Container()   // arr has indeterminate values, same for no constructor case

arr 在成员初始化器列表中时,arr 包含全零。

Container():
    arr()  // arr contains 0, 0, 0

另外,当我写下面的代码时,我得到一个错误。

Container() :
    arr 0, 1, 2 

g:\cppconsole\cppconsole\main.cpp(89): 错误 C2797: 'Container::arr': 成员初始化器列表或非静态数据成员初始化器内的列表初始化未实现

根据 C++ 的新标准,代码应该是有效的吗?如果有,是不是我的 Visual Studio 版本不支持?

为了达到同样的效果,我编写了以下代码。代码中是否存在任何潜在问题?因为我不确定代码是否正确。

Container() :
    arr( decltype(arr) 0, 1, 2  )

附:我正在使用 Microsoft Visual Studio Community 2013。

【问题讨论】:

【参考方案1】:

std::array 是一个聚合,它没有构造函数(这是故意的)。因此,当默认初始化时,它会默认初始化其元素。当值初始化时,它会对它们进行值初始化。

分析您的代码:

std::array<int, 3> arr1;  // gives me some garbage values, as expected
auto arr2 = std::array<int, 3>();  // gives me three 0, value-initialize?

arr1 是默认初始化的。 arr2 是从一个用 () 初始化的临时对象复制初始化的,即值初始化。

Container() 

这使成员 arr 默认初始化。

Container():
    arr()  // arr contains 0, 0, 0

这使用() 初始化arr,这是值初始化。

Container() :
    arr 0, 1, 2 

这是合法的 C++11,但 VS 2013 显然不支持它(它的 C++11 支持不完整)。

【讨论】:

关于聚合,为了理解你的观点,我做了一些测试。我有一个聚合:AggregateAggregate s1; default-initialises 元素,如你所说。 Aggregate s2 ; 值初始化,没问题。但是,Aggregate s3 = Aggregate(); 默认初始化。为什么?您说 从使用 () 初始化的临时对象中复制初始化,即值初始化,将对内部元素进行值初始化。 我注意到只有当聚合中有一个类类型的元素时才会出现上述情况,例如std::string或任何用户定义的类。如果聚合仅包含原始类型,Aggregate s3 = Aggregate(); 将值初始化其内部元素。为什么在聚合中添加类类型元素会阻止值初始化? @DannyYL 我倾向于说这是一个错误。据我所知,没有用户提供的 ctor 的值初始化类应该是零初始化的 (C++14 8.5/8)。 发现是Visual Studio的问题。当我使用 g++ 在命令行提示符下编译程序时,(有和没有类类型)值初始化。

以上是关于std::array 默认初始化还是值初始化?的主要内容,如果未能解决你的问题,请参考以下文章

初始化具有非默认构造函数的 std::array 项的更好方法?

编译器生成的默认构造函数是否会将std :: array中的指针初始化为nullptr?

为啥我可以从 初始化常规数组,而不是 std::array

初始化 std::array 的 std::array

std::array 初始化中的大括号省略

如何使用初始化列表构造 std::array 对象? [复制]