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

为什么显式默认的析构函数会改变C++类的移动语义?

测试代码
#include <iostream>
#include <utility>

struct A
{
    A() = default;    
    A(A const&) { std::cout << "A(A const&)" << std::endl; }    
    A(A&&)      { std::cout << "A(A&&)" << std::endl; }
};

struct B { A a; ~B() = default; };    
struct C { A a; };

int main()
{
    auto b1 = B{};
    auto b2 = B(std::move(b1)); // 调用A的拷贝构造函数A(A const&)

    auto c1 = C{};
    auto c2 = C(std::move(c1)); // 调用A的移动构造函数A(A&&)
}
差异原因

这个现象是C++标准对特殊成员函数隐式生成规则的明确规定导致的:

  • 只要类存在用户声明的析构函数,编译器就不会为该类隐式生成移动构造函数和移动赋值运算符。注意:用= default显式要求生成默认析构函数,也属于「用户声明析构函数」的范畴,同样会抑制移动函数的隐式生成。

类B的执行逻辑

B显式声明了~B() = default;,符合抑制移动函数生成的条件,没有可用的移动构造函数。此时B(std::move(b1))传入的右值会自动匹配到B隐式生成的拷贝构造函数(拷贝构造的生成不会被用户声明的析构函数抑制),拷贝构造函数会对成员a执行拷贝操作,因此调用A的拷贝构造。

类C的执行逻辑

C没有用户声明任何特殊成员函数,编译器会正常隐式生成移动构造函数,该移动构造会对每个类成员执行移动操作,因此调用A的移动构造。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 04:45:04