为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是

Posted

技术标签:

【中文标题】为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是?【英文标题】:Why std::array<int, 10> x is not zero-initialized but std::array<int, 10> x = std::array<int, 10>() seems to be?为什么 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是? 【发布时间】:2013-08-20 05:10:05 【问题描述】:

我刚刚问了两个关于数组和值初始化的问题here 和here。 但是有了这段代码,我迷路了:

#include <iostream>
#include <iomanip>
#include <array>

template <class T, class U = decltype(std::declval<T>().at(0))>
inline U f1(const unsigned int i)
T x; return x.at(i);

template <class T, class U = decltype(std::declval<T>().at(0))>
inline U f2(const unsigned int i)
T x = T(); return x.at(i);

int main()

    static const unsigned int n = 10;
    static const unsigned int w = 20;
    for (unsigned int i = 0; i < n; ++i) 
        std::cout<<std::setw(w)<<i;
        std::cout<<std::setw(w)<<f1<std::array<int, n>>(i);
        std::cout<<std::setw(w)<<f2<std::array<int, n>>(i);
        std::cout<<std::setw(w)<<std::endl;
    
    return 0;

正如预期的那样,f1 返回任意值,因为它的值不是零初始化的。但是f2 似乎只返回零值:

                   0                   0                   0
                   1                  61                   0
                   2                   0                   0
                   3                   0                   0
                   4           297887440                   0
                   5               32767                   0
                   6             4196848                   0
                   7                   0                   0
                   8           297887664                   0
                   9               32767                   0

我个人认为f2 将创建一个具有任意值的数组并将其复制/移动到x。但似乎并非如此。

所以,我有两个问题:

为什么? C++11 std::array&lt;T, N&gt; 和 C 风格的 T[N] 在这种情况下是否有相同的行为?

【问题讨论】:

T() 是一个值初始化的T。如果 T 是 C 样式的数组类型,则语法无效。 T x = ;T x; 是更普遍适用的语法。 @Casey 值初始化适用于 C 样式数组。如果T 不是简单类型说明符,即命名类型的单个标识符或关键字,则T() 是语法错误。在 C++03 中,= 仅适用于数组,简单的 是错误的。 假设的副本是关于值初始化的,但这个问题是关于默认初始化的。请重新打开并找到正确的副本,或者直接回答。 @Potatoswatter 我没有建议值初始化不适用于 C 样式数组。 simple-type-specifier 也可以是 type-name(包括 typedef 名称)或 simple-template-id。问题是关于 C++11。 请注意,5.2.3/2 定义了函数转换符号:“表达式T(),其中Tsimple-type-specifiertypename-specifier 对于 非数组 完整对象类型或(可能是 cv 限定的)void 类型,创建指定类型的纯右值,它是值初始化的 ( 8.5;没有对void() 案例进行初始化)。”它明确禁止数组类型。 【参考方案1】:

使用() 作为初始化器,不带=,会导致值初始化。对于具有隐式声明构造函数的类型,值初始化实现零初始化,顾名思义,将每个原始元素设置为0。这发生在构造函数可能运行之前,但在这种情况下,构造函数什么都不做。

因为构造函数什么都不做(它是微不足道的),所以有可能看到未初始化的数据。

对于 C 风格的数组,如果使用 = 而不是 = T(),则行为类似,因为后者是非法的。 T() 会要求将临时数组对象分配给命名对象,但无法分配数组。另一方面,= 将花括号初始化器列表分配给数组,而花括号初始化器列表是一种特殊的语法结构,既不是表达式也不是对象。

【讨论】:

以上是关于为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是的主要内容,如果未能解决你的问题,请参考以下文章

为啥我不能在 std::array< int, 3 > 的指针上使用运算符 [] 来索引值?

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

为啥 std::array::size constexpr 具有简单类型(int,double,...)而不是 std::vector (GCC)?

如何在 C++ 中比较 std::array ?

编译期间的 std::array 类成员集?

数组的 C++ 向量