使用默认的默认构造函数进行C ++ 11值初始化

时间:2014-06-04 17:32:52

标签: c++ c++11 language-lawyer

在以下示例中:

#include <iostream>

struct A {
    int z;
    A(std::string) {}
    A() = default;
};

int main() {
    char buf[1000];
    std::fill(buf, buf + 1000, 'x');
    auto a = new(buf) A{};
    std::cerr << "A.z: " << a->z << std::endl;
}

使用GCC 4.8 outputs zero编译(与Clang 3.4相同)。这似乎表明a在调用默认构造函数之前被初始化为零。

但是根据value-initialization rules on cppreference.com,在默认构造函数调用之前不应该初始化对象。类A符合C ++ 11下的项目符号#1

  

1)如果T是具有至少一个用户提供的任何类型构造函数的类类型,则调用默认构造函数。

另一个可能有用的数据点是,如果我们在上面的示例中将A() = default替换为A() {}no zero-initialization happens将如预期的那样。这似乎表明在初始示例中遵循了值初始化的第2点,这是错误的:

  

2)如果T是没有任何用户提供的构造函数的非联合类类型,则该对象被零初始化,然后调用隐式声明的默认构造函数(除非它是微不足道的)

1 个答案:

答案 0 :(得分:4)

您在C ++ 11中引用值初始化的措辞被认为是有缺陷的,请参阅Core Working Group DR 1368以及Core Working Group DR 1301中更改措辞的分辨率(显示添加粗体通过进行删除):

  

value-initialize T类型的对象意味着:

     
      
  • 如果T是(可能是cv限定的)类类型(第9条[类]),没有默认构造函数(12.1 [class.ctor])或一个默认构造函数用户提供的或删除 构造函数(12.1 [class.ctor]),然后对象是默认的 - 调用T的初始化 默认构造函数(如果T没有可访问的默认构造函数,则初始化格式错误);

  •   
  • 如果T是一个(可能是cv限定的)非联合类类型而没有用户提供的或删除的默认构造函数,那么该对象是零初始化的,如果 T的隐式声明的默认构造函数是 T有一个非平凡的默认构造函数那个构造函数被调用。 默认初始化;

  •   

一些编译器 - 我相信自3.3ish以来GCC 4.8和clang已经实施了DR 1301的解决方案。