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

C++中省略构造函数与显式default构造函数的差异探究

C++三种构造函数写法的差异详解

一、三种写法的本质区别

先明确三个核心场景的不同:

  • 完全不写构造函数:编译器会在类中没有任何用户声明的构造函数时,自动生成默认构造函数。生成的构造是否“平凡(trivial)”、是否属于用户提供的构造,完全取决于类成员的属性。
  • 显式写=default构造:主动要求编译器生成默认逻辑的构造函数,它的行为和编译器隐式生成的一致,但属于用户显式声明的构造函数。
  • 手写平凡构造(比如T() {}):这是用户自定义的构造函数,哪怕逻辑和默认生成的一模一样,也会让类的构造失去“平凡性”,同时属于用户提供的构造函数。

二、你的示例:example1和example2的区别

先看你给出的代码:

struct someint {
    int n;
    someint() : n(0) {} // 自定义构造,不是编译器生成的默认构造
};

class example1 {
public:
    someint n;
};

class example2 {
public:
    someint n;
    example2() = default;
};

在这个例子里,两者的默认构造行为完全一致——都会调用someint的自定义构造函数初始化成员n。但在类的属性上有两个关键细微区别:

  1. 是否属于“用户提供的构造函数”:
    • example1的默认构造是编译器隐式生成的,不算用户提供的;
    • example2的=default构造是你显式声明的,属于用户提供的构造。
      这个差异在判断类是否为**聚合类(aggregate)**时会体现:有用户提供的构造函数的类不能被当作聚合类。不过在你的例子里,因为someint有自定义构造,所以example1和example2都不是聚合类,这个区别暂时看不出来。
  2. 模板元编程/SFINAE场景:
    某些模板代码会检查类是否有用户声明的构造函数,这时example2会被识别为有用户声明的构造,而example1不会。

除此之外,在日常的对象初始化、继承等场景下,两者没有任何功能差异,只是代码风格上的选择。

三、三种写法的完整对比

  • 完全省略构造:
    • 只有当类里没有任何用户写的构造函数时,编译器才会生成默认构造;
    • 生成的构造是否平凡,取决于所有成员的构造是否平凡;
    • 不属于用户提供的构造函数。
  • =default构造:
    • 哪怕类里有其他构造函数(比如带参数的),你也可以声明=default的默认构造;
    • 构造的逻辑和编译器隐式生成的完全一致,但属于用户提供的构造;
    • 构造的平凡性和隐式生成的一致(比如如果所有成员都是平凡构造,那这个=default构造也是平凡的)。
  • 手写平凡构造:
    • 比如T() {},哪怕什么都不做,也属于用户自定义构造,会让类的构造失去平凡性;
    • 一旦手写了这个构造,编译器就不会再隐式生成默认构造。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 13:16:59