显式声明默认行为析构函数后,类是否仍生成默认移动构造函数?
C++显式声明析构函数后默认移动构造函数的生成规则
结论
当你显式声明了类的析构函数(哪怕它的行为和默认析构完全一致),编译器不会自动生成默认移动构造函数,这是C++11及后续标准明确规定的规则。
规则依据
C++标准规定:如果类显式声明了拷贝构造函数、拷贝赋值运算符、析构函数中的任意一个,编译器将不再自动生成默认的移动构造函数和移动赋值运算符。显式声明析构函数会触发这个抑制逻辑,和析构函数的具体实现无关。
你的测试代码分析
你写的测试代码其实已经能验证这个结论:
- 当注释掉
~B(){}时,编译器会为B生成默认移动构造函数,它会调用成员变量A的移动构造,运行时会输出a move ctor.。 - 当打开
~B(){}的注释后,编译器不再生成B的移动构造函数。此时B b2(std::move(b))会尝试寻找可用的构造函数,因为编译器仍会生成默认拷贝构造函数(显式声明析构不会抑制拷贝构造),所以会调用B的默认拷贝构造,进而触发A的拷贝构造,运行时输出a copy ctor.——这就说明移动构造没有被生成。
更严谨的编译期验证方法
除了运行时输出,还可以用C++标准库的类型特性做编译期检查,直接验证类是否可移动构造:
#include <type_traits> class B { public: ~B() {} }; // 编译期断言:B应该不可移动构造 static_assert(std::is_move_constructible_v<B> == false, "B is move constructible, which contradicts the rule");
如果这段代码能正常编译通过,就证明B确实没有默认移动构造函数;如果编译失败(断言触发),则说明规则未生效(这种情况通常是编译器版本不支持C++11及以上标准)。
内容的提问来源于stack exchange,提问作者akanesora
相关产品推荐
相关产品推荐

