为什么调用复制构造函数而不是移动构造函数?

fiz*_*uzz 1 c++ copy-constructor move-constructor move-semantics c++11

我有以下代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

输出是default constructor copy constructor。请告诉我是右值引用push_back(T&&)吗?什么时候调用复制构造函数?

眠りネ*_*ネロク 7

问题出在a参数中AddData()

void AddData(const A&& a) // <-- const reference!!!
{
    aList.push_back(std::move(a)); // selects push_back(const A&)
}
Run Code Online (Sandbox Code Playgroud)

a上面的参数是一个右值引用。您正在使用的标记一个对象。const std::move()const

当涉及到移动语义时,const使用std::move()for move标记一个对象没有任何影响,因为您不能从一个const对象移动(即,您需要更改被移动的对象,但它是const限定的)。

右值引用不绑定到const对象,但const左值引用绑定。结果,push_back(const A&)选择了重载而不是重载push_back(A&&),因此A对象是复制构造的。


解决方案

改用非const右值引用:

void AddData(A&& a) // <-- non-const reference
{
    aList.push_back(std::move(a)); // selects push_back(A&&)
}
Run Code Online (Sandbox Code Playgroud)

  • 你的答案很好。我只是太迂腐了。`const` 右值引用参数函数没有为 `std::string`_ 或任何其他标准 C++ 类型定义语义,但可以为自己的类自由定义自己的 `const&amp;&amp;` 语义。 (2认同)