为何C++中编译器生成的默认构造函数优于手动编写的空构造函数
C++中
= default;声明的默认构造函数优于空函数体构造函数的原因 如果默认构造函数的函数体(或是后续会学到的initializer list)中没有任何操作,你应该使用
= default;而非{}。这不仅能更明确地表明你定义的是default default constructor,还有几个不易察觉的技术原因使得编译器生成的版本是更优选择。
- 平凡性(triviality)判定差异:用
= default;声明的默认构造函数在满足条件时会被判定为平凡构造函数,而手动写的空函数体ClassName(){}一定不属于平凡构造函数。平凡构造函数所属的类属于平凡类型,C++允许对平凡类型直接用memcpy、memset等内存操作直接处理对象,运行性能更优;同时平凡类型可以满足常量求值的相关要求,能正常在编译期上下文中使用。 noexcept属性判定差异:编译器生成的默认构造函数会自动按标准规则推导noexcept属性,只要它调用的所有基类、成员的默认构造函数都是noexcept的,生成的默认构造函数也会自动附带noexcept属性。而手动写的空函数体构造函数默认是不带noexcept的,除非你手动显式声明,这会直接压缩编译器的优化空间,也会让std::is_nothrow_default_constructible这类类型萃取的结果不符合预期。- 显式/隐式构造判定差异:编译器生成的无参默认构造函数默认属于隐式构造函数,支持
ClassName obj;这类常规的隐式默认构造写法;而如果你手动写了用户提供的默认构造函数,在类包含需要显式构造的成员等特殊场景下,可能会改变构造函数的显式属性,导致原本合法的聚合初始化、隐式构造代码编译失败。 constexpr支持差异:C++20及之后的标准中,满足要求的= default;默认构造函数可以自动成为constexpr构造函数,不需要你手动添加constexpr关键字。而手动写的空构造函数需要你主动声明constexpr才能在编译期上下文使用,漏加就会直接丧失编译期求值的能力。- 特殊成员函数的隐式生成规则差异:如果你手动声明了空函数体的默认构造函数,会影响其他特殊成员函数(比如移动构造函数、移动赋值运算符)的隐式生成规则,部分场景下编译器会停止隐式生成移动相关的函数,导致对象拷贝、传递的性能下降。而用
= default;声明默认构造函数不会触发这类不必要的隐式生成阻断。
内容的提问来源于stack exchange,提问作者baby_panda
相关产品推荐
相关产品推荐

