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

C++11 value-initialization with defaulted default constructor

本文关键字:默认 初始化 构造函数 c++      更新时间:2023-10-16

示例如下:

#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编译输出为零(与Clang 3.4相同)。这似乎表明a在调用默认构造函数之前被零初始化。

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

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

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

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

您引用的c++ 11中值初始化的措辞被认为是有缺陷的,请参阅核心工作组DR 1368和核心工作组DR 1301的决议,该决议更改了措辞(显示添加加粗和删除通过):

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

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

  • 如果T是一个(可能是cv限定的)非联合类类型,没有用户提供的或已删除的默认构造函数,则对象是零初始化的,如果T的隐式声明的默认构造函数是 T有一个非简单的默认构造函数,则调用该构造函数。 default-initialized ,

一些编译器——我相信GCC 4.8和clang从3.3开始——已经实现了DR 1301的分辨率