为什么编译器在没有必要的情况下将零放入数组?

Mik*_*ail -2 c++ arrays initialization

我试图了解编译器何时应该初始化数组以及何时应该默认初始化数组.我正在尝试两个选项:一个原始数组,另一个在结构中聚合的数组:

const int N = 1000;

struct A 
{
  uint32_t arr[N];

  A() = default;
};

void print(uint32_t* arr, const std::string& message)
{
  std::cout << message << ": " << 
    (std::count(arr, arr + N, 0) == N ? "all zeros" : "garbage") << std::endl;
}

int main()
{
  uint32_t arrDefault[N];
  print(arrDefault, "Automatic array,  default initialization");

  uint32_t arrValue[N] = {};
  print(arrValue, "Automatic array,  value   initialization");

  uint32_t* parrDefault = new uint32_t[N];
  print(parrDefault, "  Dynamic array,  default initialization");

  uint32_t* parrValue = new uint32_t[N]();
  print(parrValue, "  Dynamic array,  value   initialization");

  A structDefault;
  print(structDefault.arr, "Automatic struct, default initialization");

  A structValue{};
  print(structValue.arr, "Automatic struct, value   initialization");

  A* pstructDefault = new A;
  print(pstructDefault->arr, "  Dynamic struct, default initialization");

  A* psstructValue = new A();
  print(psstructValue->arr, "  Dynamic struct, value   initialization");
}
Run Code Online (Sandbox Code Playgroud)

以下是我对clangVC++的看法:

Automatic array,  default initialization: garbage
Automatic array,  value   initialization: all zeros
  Dynamic array,  default initialization: garbage
  Dynamic array,  value   initialization: all zeros
Automatic struct, default initialization: all zeros
Automatic struct, value   initialization: all zeros
  Dynamic struct, default initialization: garbage
  Dynamic struct, value   initialization: all zeros
Run Code Online (Sandbox Code Playgroud)

gcc的输出仅在第一行中有所不同,其中它也放置"全零".

从我的观点来看,他们都错了,我期待的是:

Automatic array,  default initialization: garbage
Automatic array,  value   initialization: all zeros
  Dynamic array,  default initialization: garbage
  Dynamic array,  value   initialization: all zeros
Automatic struct, default initialization: garbage
Automatic struct, value   initialization: garbage
  Dynamic struct, default initialization: garbage
  Dynamic struct, value   initialization: garbage
Run Code Online (Sandbox Code Playgroud)

即输出对于原始数组(gcc除​​外)是正常的:我们有默认的垃圾和值的零.大.但是对于一个结构我会期望一直有垃圾.从默认初始化:

默认初始化在以下三种情况下执行:

  1. ...
  2. ...
  3. 在构造函数初始值设定项列表中未提及基类或非静态数据成员且调用该构造函数时.

默认初始化的效果是:

  • 如果T是非POD(直到C++ 11)类类型,...
  • 如果T是数组类型,则数组的每个元素都是默认初始化的;
  • 否则,什么都不做:具有自动存储持续时间的对象(及其子对象)被初始化为不确定值.

在我的示例中,我有一个非静态数据成员,它在构造函数初始化列表中没有提到,它是一个POD类型的数组.无论我的结构是如何构造的,我都希望它留下不确定的值.

我的问题是:

  • 为什么编译器违反了这个?我的意思是,为什么他们在没必要的时候放零,浪费我的运行时间?我的读数错了吗?
  • 我如何强制执行此类行为以确保我不会浪费我的运行时使用零填充数组?
  • 为什么gcc为自动数组执行值初始化?

Bau*_*gen 5

A structValue{}; 是聚合初始化,所以保证0.

由于A没有用户提供构造函数,因为显式默认构造函数不计算,因此同样适用于值初始化A* psstructValue = new A();.

对于默认的初始化情况:读取未初始化的变量是UB,未定义的行为是未定义的.编译器可以随心所欲地做到这一点.向你显示0和崩溃一样合法.也许你偶然读到的内存中有0个.也许编译器感觉像0初始化.从标准的角度来看,两者都同样好.

话虽这么说,在使用Release/optimize版本进行测试时,您有更好的机会看到垃圾.调试版本往往会做额外的事情来帮助诊断问题,包括做一些额外的初始化.

(对于记录:gcc和clang -O3似乎在我的Linux系统上没有进行不必要的初始化.但是,我对每个案例都得到了"全部为零".这似乎是偶然的.)