16

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

#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++11std::array<T, N>和 C 风格T[N]在这种情况下是否有相同的行为?
4

1 回答 1

18

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

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

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

于 2013-08-19T07:48:51.890 回答