在以下示例中:
#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是没有任何用户提供的构造函数的非联合类类型,则该对象被零初始化,然后调用隐式声明的默认构造函数(除非它是微不足道的)
答案 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的解决方案。