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

mto*_*ssi 7 c++ language-lawyer c++11

在以下示例中:

#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;
}
Run Code Online (Sandbox Code Playgroud)

用GCC 4.8编译输出零(与Clang 3.4相同的行为).这似乎表明a在调用默认构造函数之前进行了零​​初始化.

但是根据cppreference.com上的值初始化规则,在默认构造函数调用之前不应该初始化该对象.类A符合C++ 11下的要点#1:

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

另一种可能是有用的数据点是,如果我们更换A() = defaultA() {}在上面的例子中,没有零初始化发生的预期.这似乎表明在初始示例中遵循了值初始化的项目符号#2,这将是错误的:

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

Cas*_*sey 5

措辞,你举在C ++ 11是有缺陷的认为值初始化,请参阅核心工作组DR 1368和分辨率核心工作组DR 1301改变了措辞(显示与添加大胆和删除与通过罢工):

值初始化的类型的对象T是指:

  • if T是一个(可能具有cv资格的)类类型(第9条[class]),没有默认构造函数(12.1 [class.ctor]),或者是由用户提供或删除默认构造函数(12.1 [class.ctor]) ),则该对象是 T的默认初始化的默认构造函数(如果T没有可访问的默认构造函数,则初始化格式不正确)

  • 如果T是(可能具有cv资格的)非工会类类型,而没有用户提供或删除的默认构造函数,则该对象将初始化为零,并且,如果T的隐式声明的默认构造函数 T具有非平凡的默认构造函数,则该对象构造函数被调用。 默认初始化 ;

一些编译器(我相信自3.3ish起就是GCC 4.8和clang)已经实现了DR 1301的分辨率。