为什么C++中default声明的构造函数会对类成员执行零初始化?
问题复现
测试代码如下:
#include <iostream> struct A { int x; A() {}; }; struct B { int x; B() = default; }; int main() { int x = 5; x = 7; printf("before: %d\n", x); new(&x) A(); printf("%d\n", x); new(&x) B(); printf("%d\n", x); }
运行输出结果:
before: 7 7 0
核心原因
这个差异是C++标准对不同类型默认构造函数和值初始化规则的明确规定导致的,核心区别在于两个类的默认构造函数是否属于「用户提供」的范畴:
- 类
A的A() {}是用户手动实现的空构造函数,属于用户提供的默认构造函数 - 类
B的B() = default是显式要求编译器生成默认构造,类内声明的=default默认构造不属于用户提供的默认构造函数
结合值初始化规则就能解释执行结果:
你用placement new构造对象时用的是A()和B()的写法,这属于C++的值初始化场景,规则如下:
- 当值初始化的类类型拥有「用户提供的默认构造函数」时,直接调用该构造函数,不会做额外处理:
类A的空构造函数没有对x做任何赋值操作,所以x保留了原本内存里的值7,第一次输出为7。 - 当值初始化的类类型拥有「非用户提供的默认构造函数」时,会先把整个对象的内存区域做零初始化,再调用默认构造函数:
类B的默认构造是编译器生成的空实现,零初始化步骤会把x对应的内存置为0,调用构造函数也没有修改x的值,所以第二次输出为0。
补充说明:如果你用的是默认初始化写法(比如new(&x) B不带括号),不会触发零初始化步骤,x会保留原来的7,不会被置零。
内容的提问来源于stack exchange,提问作者vladon
相关产品推荐
相关产品推荐

