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

时间:2016-07-04 16:14:17

标签: 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");
}

以下是我为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

gcc的输出仅在第一行有所不同,它也会放置&#34;全部为零&#34;。

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

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

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

  

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

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

    默认初始化的效果是:

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

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

我的问题是:

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

2 个答案:

答案 0 :(得分:5)

A structValue{};是聚合初始化,因此保证为0。

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

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

话虽这么说,在使用Release /优化版本进行测试时,您更有可能看到垃圾。调试版本往往需要额外的东西来帮助诊断问题,包括做一些额外的初始化。

(对于记录:gcc和clang与-O3乍一看似乎没有在我的Linux系统上进行不必要的初始化。尽管如此,我得到了#34;全部为零&#34;对于每一个案例。这似乎是由机会。)

答案 1 :(得分:0)

另一个答案并没有真正解决REASON与语言规范的差异。

实际原因是初始化过程的工作原理。

问问自己如何知道某些内容是否已初始化的问题。

这就是为什么需要初始化静态数据的原因,而不需要初始化静态数据的原因。如果你没有先通过并将所有静态数据清零,那么静态动态初始化过程(查找它)基本上是不可能的。

你会经常遇到两个静态问题,它们在初始化时倾斜地互相引用,一切都崩溃了。

因此,如果没有这个规则,C ++基本上不可能为其编写编译器。虽然还有其他初始化方案没有这个要求,但是需要对语言进行大修才能实现它们。