You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何=default默认构造函数仅适配类指针?栈实例化报错解析

问题

我编写了一个带默认构造函数的类示例,代码如下:

class Foo {
public:
    int x;
    Foo() = default;
};

int main() {    
    for (int i = 0; i < 100; i++) {
        Foo* b = new Foo();
        std::cout << b->x << std::endl;
    }

这段代码运行正常,但当我在栈上实例化类对象(如Foo b)时,却出现“未初始化的局部变量'b'被使用”的错误。然而,若将构造函数改为Foo() {},Foo b的实例化就能正常运行,且b.x会输出预期的随机垃圾值。

请问为何使用=default的默认构造函数无法在栈上实例化类?我使用MSVC C++17编译代码。

解答

这是因为=default和手动编写空构造函数Foo() {}在C++标准中的语义完全不同:

  • 使用Foo() = default;时,这个构造函数属于平凡默认构造函数,它的行为和C语言结构体的默认初始化规则一致:栈上的对象执行默认初始化时,不会自动初始化成员变量。MSVC编译器会检测到这种未初始化的局部变量使用,进而抛出警告或错误。
  • 手动编写Foo() {}时,这个构造函数是非平凡构造函数,它的函数体为空,但编译器会认为成员变量已经被构造函数处理过,不会再触发未初始化变量的检测,因此你能看到b.x输出随机垃圾值。

另外需要注意初始化方式的区别:

  • 你用new Foo()时,带括号的形式会触发值初始化:即便构造函数是平凡的,也会对对象成员进行值初始化(比如int类型会被置零),所以堆上的对象不会有未初始化问题。
  • 栈上的Foo b执行的是默认初始化,平凡构造函数不会初始化成员,这才导致了编译器的报错。

本质上,=default保留了C风格的默认初始化行为,而手动空构造函数改变了初始化语义,让编译器不再检测成员未初始化的问题。

内容的提问来源于stack exchange,提问作者Kaiyakha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 12:45:52