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

为何移除move constructor后调用copy constructor而非默认move constructor?

关于C++移动构造函数调用的疑问解答

嘿,这个问题问得特别到位,刚好戳中了C++11里默认移动构造函数生成的一个容易被忽略的规则点!我来一步步给你拆解清楚:

先理清你的代码执行场景

你用了编译参数-fno-elide-constructors,这会关闭返回值优化(RVO),所以ABC c1 = ABC()的执行流程会分成两步:

  1. 创建临时的ABC()对象,触发默认构造函数;
  2. 把这个临时右值对象“转移”给c1,这时候编译器会尝试调用移动构造或拷贝构造。

核心原因:默认移动构造函数的生成规则

C++11标准明确规定:当你自定义了拷贝构造函数、拷贝赋值运算符、析构函数中的任意一个时,编译器不会自动生成默认的移动构造函数。

回到你的代码里:

  • 当你保留自定义的move constructor时,编译器会优先用它来处理右值临时对象,所以输出move construction;
  • 当你移除自定义移动构造后,你的类里还存在自定义的拷贝构造函数!这就触发了上面的规则——编译器不会再帮你生成默认的移动构造函数。

这时候,当需要处理右值临时对象时,因为没有可用的移动构造函数,编译器会退而求其次:右值可以被绑定到const ABC&类型的参数(也就是拷贝构造函数的参数),所以最终调用的是拷贝构造函数,输出copy construction。

验证:如何让编译器生成默认移动构造?

如果你想在保留自定义拷贝构造的同时,让编译器生成默认移动构造,可以显式声明:

#include <iostream>
class ABC {
public:
    ABC() { std::cout<< "default construction" << std::endl; }
    ABC(const ABC& a) { std::cout << "copy construction" << std::endl; }
    // 显式让编译器生成默认移动构造
    ABC(ABC&&) = default;
};
int main() {
    ABC c1 = ABC();
    return 0;
}

用同样的编译参数-fno-elide-constructors -std=c++11编译运行,就会输出:

default construction
move construction

给新手的小总结

记住这个关键规则:只要你手动定义了拷贝相关的成员(拷贝构造、拷贝赋值、析构),编译器就不会自动生成移动构造/移动赋值——这是C++11为了兼容旧代码的行为而设计的。如果需要移动语义,要么自己写移动构造,要么显式用= default;让编译器帮你生成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 20:57:28