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

Why is copy constructor called rather than move constructor?

提问人:fizzbuzz 提问时间:6/29/2020 最后编辑:JFMRfizzbuzz 更新时间:7/1/2020 访问量:308

问:

我有以下代码:

#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 constructorpush_back(T&&)

C++ C++11 复制构 语义 移动 构造函数

评论


答:

8赞 JFMR 6/29/2020 #1

问题出在以下参数上:aAddData()

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

上面的参数是常量右值引用。您正在使用对象进行标记。astd::move()const

当涉及到移动语义时,使用 for moving 标记对象不起作用,因为您不能从对象中移动(即,您需要更改从中移动的对象,但它是限定的)。conststd::move()constconst

右值引用不绑定到对象,但左值引用绑定到对象。因此,将选择重载而不是重载,因此将复制构造对象。constconstpush_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&&)
}

评论

1赞 Mooing Duck 7/1/2020
“用 std::move() 标记一个 const 对象进行移动没有效果” 从技术上讲,只需转换为 Rvalue,就会给你留下一个有效的 .它只是没有一个需要 的构造函数,所以回退到 .从理论上讲,人们可以用构造函数创建一个类。std::moveconst&&std::stringconst&&const&const&&
1赞 JFMR 7/1/2020
@MooingDuck 是的,你是对的,总是有施法的效果。但是,我想说的是,在移动语义方面对对象没有影响,因为我认为右值引用参数函数(例如,类型)没有定义的语义。我希望或多或少清楚为什么选择过载——毕竟没有过载。std::move()std::move()constconstconst A&&vector<A>::push_back(const A&)vector<A>::push_back(const A&&)
2赞 Mooing Duck 7/1/2020
你的答案很好。我只是太迂腐了。右值引用参数函数没有std::string 或任何其他标准 C++ 类型定义的语义,但可以自由地为自己的类定义自己的语义。constconst&&