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

C++11中=default默认构造函数与空构造函数{}的区别是什么?

为什么在C++11中优先用= default而非空构造函数?

嗨,这个问题问得特别实在!很多刚接触C++11的开发者都会纠结这两种写法的区别,我来给你拆解清楚核心差异:

1. 保留默认构造函数的「平凡性」特性

用= default让编译器生成的构造函数,属于平凡默认构造函数(trivial default constructor),而你手动写的空构造函数MyClass() {}是非平凡的。这个区别会影响很多场景:

  • 标准库类型特性判断:比如std::is_trivial<T>会返回true(针对用= default的类),这会让你的类符合某些标准库算法或容器的优化条件——比如std::vector对平凡类型扩容时,可以直接复制内存块,而非平凡类型需要逐个调用构造函数,效率差异明显。
  • 内存操作合法性:平凡类型可以安全使用memcpy、memset这类C风格内存函数,非平凡类型这么做会导致未定义行为。

举个代码例子直观感受:

#include <type_traits>
#include <iostream>

class DefaultCtor {
public:
    DefaultCtor() = default; // 编译器生成的平凡构造函数
    int val;
};

class EmptyCtor {
public:
    EmptyCtor() {} // 用户定义的非平凡构造函数
    int val;
};

int main() {
    std::cout << "DefaultCtor is trivial? " << std::is_trivial<DefaultCtor>::value << "\n"; // 输出1(true)
    std::cout << "EmptyCtor is trivial? " << std::is_trivial<EmptyCtor>::value << "\n";     // 输出0(false)
}

2. 语义更明确,避免歧义

= default的写法相当于直接告诉编译器和其他开发者:「我就要你原本自动生成的那个默认构造函数,没有任何自定义逻辑」。而空构造函数MyClass() {}看起来像是你特意定义了一个构造函数,哪怕现在里面是空的,后续维护者可能会误以为这里需要加初始化逻辑,不小心修改了它的行为——这就违背了你原本只是想恢复默认构造函数的意图。

3. 处理特殊成员的差异

当你的类包含const成员、引用成员或者没有默认构造函数的类成员时:

  • 用= default生成的构造函数会直接编译报错,因为编译器无法自动初始化这些特殊成员;
  • 手动写的空构造函数如果不初始化这些成员,同样会报错,但你可以在初始化列表里手动指定初始化逻辑——不过这时候你已经不是在模拟默认构造函数的行为了,而是自定义构造逻辑。

另外,当你定义了其他构造函数(比如MyClass(int num)),编译器会自动停止生成默认构造函数。这时候用= default可以简洁地让编译器重新生成那个原本会被抑制的默认构造函数,同时保留它的平凡性;而手动写空构造函数虽然也能达到「有默认构造函数」的目的,但会失去平凡性带来的优化。

4. 编译器优化空间更大

编译器对自己生成的默认构造函数非常熟悉,能做更多针对性优化——比如在某些场景下直接省略构造函数调用,或者更高效地处理成员初始化。而用户定义的空构造函数,哪怕逻辑为空,编译器也会把它当作一个普通的用户函数,可能无法触发这些优化。

总结一下:如果你的需求就是「拥有编译器原本会自动生成的那个默认构造函数」,选= default;如果需要在构造函数里加自定义逻辑(哪怕现在是空的,未来可能要加),再手动写空构造函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:23:49