C++ &引用;“违约”;移动构造函数和赋值-奇怪的行为

C++ &引用;“违约”;移动构造函数和赋值-奇怪的行为,c++,c++11,move,move-semantics,C++,C++11,Move,Move Semantics,我有一个简单的例子,这个类有两个成员变量。我声明了一个副本和一个移动构造函数,它们是=default,这将迫使编译器为我生成它们。现在我的问题是。当使用移动构造函数(或赋值)时,为什么我从中移动的对象保持不变 例如,如果我有: myclass obj(4, 5); myclass obj2 = std::move(4, 5); 据我所知,在第二行之后,obj将包含“nothing”,因为它将被移动到obj2,其中将包含值(4,5)。我知道我不习惯纠正这里的术语 完整代码: #include &

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

例如,如果我有:

myclass obj(4, 5);
myclass obj2 = std::move(4, 5);
据我所知,在第二行之后,
obj
将包含“nothing”,因为它将被移动到
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";
}
#包括
#包括
模板
类对
{
公众:
T1优先;
T2秒;
公众:
//建设者
constexpr Pair()=默认值;
常量表达式对(常量T1和\u第一,常量T2和\u第二)
:第一(第一)、第二(第二)
{}
constexpr对(T1&&U第一,T2&&U第二)
:第一(std::forward(_first)),第二(std::forward(_second))
{}
constexpr Pair(const Pair&)=默认值;
constexpr Pair(Pair&&)=默认值;
//分配
Pair&运算符=(const Pair&)=默认值;
Pair&运算符=(Pair&&)=默认值;
};
int main()
{
对p(1,2);
对p2=p;//都很好,p={1,2}和p2={1,2}
对p3=std::move(p);//p={1,2}和p3={1,2}
//为什么p没有“移动”到p3??
//p应该是空的??
//移动分配也会发生同样的情况。为什么?

std::coutint
的默认移动只是一个副本。

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

默认移动构造函数和移动赋值将对所有成员调用
std::move
。与副本一样,默认复制构造函数只调用所有成员的副本


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

默认的移动构造函数和移动赋值将简单地调用所有成员的
std::move
。与副本一样,默认的复制构造函数简单地调用所有成员的副本


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

我认为所有构建类型都是一样的,不是吗?哦,我不知道。因此,如果我对p(“1”,“2”);它会像我预期的那样工作?反问句。已经测试过了。我认为所有构建类型都是一样的,不是吗?哦,我不知道。所以如果我对p(“1”,“2”)进行配对;它会像我期望的那样工作吗?反问句。已经测试过了。它怎么会包含“nothing”?你怎么做一个
int
存储“nothing”?你可以复制它,然后将它设置为
0
,但这比复制它要复杂得多,移动至少要和复制一样有效,因此如果编译器通过做额外的工作来“移动”简单值。它如何包含“nothing”?如何使
int
存储“nothing”?您可以复制它,然后将其设置为
0
,但这将比仅复制它要做更多的工作,并且移动意味着至少与复制一样高效,因此如果编译器“移动”,它将是哑的“通过做额外的工作来简化值。从
移动的向量
处于有效但未指定的状态。它不一定为空。从
移动的向量
处于有效但未指定的状态。它不一定为空。”。