"默认"移动构造函数和赋值 - 奇怪的行为

时间:2015-11-25 15:08:07

标签: c++ c++11 move move-semantics

所以我有一个有两个成员变量的类的简单例子。我已经声明了= default的副本和移动构造函数,它会强制编译器为我生成它们。现在我的问题是这个。当使用移动构造函数(或赋值)时,为什么我移动的对象保持不变?

例如,如果我有:

myclass obj(4, 5);
myclass obj2 = std::move(4, 5);

根据我的理解,在第二行obj将包含"没有"之后,因为它将被移动到obj2,其值为(4, 5) 。我知道我在这里没有用来纠正条款......

完整代码:

#include <iostream>
#include <utility>

template<class T1, class T2>
class Pair
{
public:
    T1 first;
    T2 second;

public:
    //CONSTRUCTORS
    constexpr Pair() = default;

    constexpr Pair(const T1& _first, const T2& _second)
        : first(_first), second(_second)
    {}

    constexpr Pair(T1&& _first, T2&& _second)
        : first(std::forward<T1>(_first)), second(std::forward<T2>(_second))
    {}

    constexpr Pair(const Pair&) = default;
    constexpr Pair(Pair&&)      = default;

    //ASSIGNMENT
    Pair &operator=(const Pair&) = default;
    Pair &operator=(Pair&&)      = default;
};

int main()
{
    Pair<int, int> p(1, 2);

    Pair<int, int> p2 = p; //all good, p = {1, 2} and p2 = {1, 2}

    Pair<int, int> p3 = std::move(p); //p = {1, 2} and p3 = {1, 2}
                                    //why isn't p "moved" into p3??
                                    //p should be empty??

    //same thing occurs with the move assignment. why?

    std::cout << p.first << " " << p.second << "\n";
    std::cout << p2.first << " " << p2.second << "\n";
    std::cout << p3.first << " " << p3.second << "\n";
}

实例:http://coliru.stacked-crooked.com/a/82d85da23eb44e66

2 个答案:

答案 0 :(得分:3)

int的默认移动只是一个副本。

答案 1 :(得分:2)

默认的移动构造函数和移动分配只会向所有成员调用std::move。就像副本一样,默认的复制构造函数只需调用所有成员的副本。

您的代码是正确的,在调用std::move后,移动的数据仍然存在是正常的。为什么?因为基元上的std::move复制它们。编译器不会生成将int移动到0的代码,因此它是一个简单的副本。但是,如果您对包含更复杂的类型(例如std::vector<int>),则移动的向量将有效地结束为空。