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

为何编译器调用move后选择拷贝构造函数?右值引用相关疑问

嘿,我来帮你把这些C++里的细节拆解清楚,一个个解决你的疑问~

关于拷贝构造、移动构造与右值引用的疑问解答

1. 为什么编译器会选择拷贝构造而非报错?

当你手动实现了拷贝构造函数后,C++编译器确实会自动禁用默认的移动构造函数——这是标准规定的行为,目的是避免自动生成的移动构造和你自定义的拷贝构造逻辑冲突。

但这里有个关键的兼容设计:右值在找不到匹配的移动构造函数时,会尝试绑定到const T&类型的参数,也就是你的拷贝构造函数。因为const左值引用是可以接受右值的(临时对象、字面量这些都是右值),编译器会把这个右值隐式转换为可被const T&绑定的形式,进而调用拷贝构造。

这种设计是为了保证新旧代码的兼容性:在C++11引入移动语义之前,所有对象拷贝都是用拷贝构造,所以即使现在你没写移动构造,代码依然能像以前一样正常工作,而不是直接报错。

2. 右值引用能否作为左值引用的参数?

这得分两种情况看:

  • 如果是const左值引用(const T&):完全可以!C++标准允许右值绑定到const左值引用上,这也是上面拷贝构造能被调用的核心原因。这种设计让你可以用同一个函数同时处理左值和右值,不用单独写重载。
  • 如果是非const左值引用(T&):不行!非const左值引用要求绑定到一个可修改的左值(比如有名字的变量),右值是临时的、不可被修改的(或者说修改了也没意义),所以编译器会直接报错,提示「无法将右值绑定到非const左值引用」。

结合你的输出结果「Thanks」来理解

假设你的代码大概是这样的:

#include <iostream>
class Demo {
public:
    Demo() {}
    // 自定义拷贝构造,输出Thanks
    Demo(const Demo&) {
        std::cout << "Thanks" << std::endl;
    }
    // 没有定义移动构造函数
};

int main() {
    // 用临时右值对象初始化obj
    Demo obj = Demo();
    return 0;
}

这里Demo()是一个临时右值,因为没有移动构造函数,编译器就会调用你自定义的拷贝构造函数,所以输出了「Thanks」。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 08:17:33