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

为何调用拷贝构造函数而非移动构造函数?代码相关疑问咨询

咱们先看你写的这段C++代码和运行结果:

#include <bits/stdc++.h>
using namespace std;
class A {
public:
    A(const A& a) noexcept { cout << "copy constructor" << endl; }
    A& operator=(const A& a) noexcept { cout << "copy assignment operator" << endl; }
    A(A&& a) noexcept { cout << "move constructor" << endl; }
    A& operator=(A&& a) noexcept { cout << "move assignment operator" << endl; }
    A() { cout << "default constructor" << endl; }
};
vector<A> aList;
void AddData(const A&& a) {
    aList.push_back(std::move(a));
}
int main() {
    AddData(A());
    return 0;
}

运行输出:default constructor copy constructor

接下来逐个解答你的三个问题:

1. 是否调用了右值引用版本的push_back(T&&)?

并没有。实际调用的是push_back(const T&)这个接受const左值引用的重载版本,而非右值引用版本的push_back(T&&)。

2. 拷贝构造函数何时被调用?

拷贝构造函数是在push_back内部执行对象复制时被调用的。具体来说,vector需要在自己的内存空间里构造一个新的A对象,因为传入的参数是const左值,所以只能通过拷贝构造来创建这个新对象。

3. 为何调用的是拷贝构造函数而非移动构造函数?

问题的核心出在AddData的参数声明const A&& a上——你把右值引用声明成了const限定的右值引用。当你对这个参数调用std::move(a)时,返回的是const A&&类型,而标准库中vector::push_back(T&&)要求的是非const的右值引用,因为移动操作本质上需要修改被移动的对象(把它的资源转移走,让原对象处于可安全析构的状态)。

由于不存在push_back(const T&&)这个重载,编译器会匹配最兼容的重载,也就是push_back(const T&),这个重载会调用拷贝构造函数来复制对象。

如果把AddData的参数改成A&& a(去掉const修饰),那么std::move(a)返回的就是非const的右值引用,此时就会触发push_back(T&&)重载,进而调用移动构造函数,输出就会变成default constructor move constructor了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 11:32:45