Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ move构造函数和std::move混淆_C++_C++11_Move_Rvalue Reference - Fatal编程技术网

C++ move构造函数和std::move混淆

C++ move构造函数和std::move混淆,c++,c++11,move,rvalue-reference,C++,C++11,Move,Rvalue Reference,我正在阅读有关移动构造函数和移动赋值运算符的内容。 老实说,我现在得到的只是困惑。现在我有一节课: class A{ public: int key; int value; A(){key = 3; value = 4;} //Simple move constructor A(A&& B){ A.key = std::move(B.key); A.value = std::move(B.value);}

我正在阅读有关移动构造函数和移动赋值运算符的内容。 老实说,我现在得到的只是困惑。现在我有一节课:

class A{
  public:
    int key;
    int value;
    A(){key = 3; value = 4;}
    //Simple move constructor
    A(A&& B){ A.key = std::move(B.key); 
              A.value = std::move(B.value);}
};
  • 我认为
    B
    是一个右值引用,为什么您可以将
    std::move
    应用于一个右值引用的成员
  • 在移动了
    B.key
    B.value
    之后,这两个项都已失效,但是
    B
    作为类
    A
    的对象如何失效
  • 如果我有
    A(A())
    A()
    显然是一个rvlaue,那么
    A()
    可以被
    std::move
    移动吗?为什么
  • 类似地,如果我有一个函数

    int添加(int&&z){
    int x=标准:移动(z);
    int y=标准:移动(z);
    返回x+y;
    }

  • 如果我调用
    add(5)
    ,如何移动
    5
    ,为什么? 请注意,
    z
    已经移动了两次,在第一次移动
    z
    之后,它已经无效,您如何再次移动它

  • 当定义
    foo(T&&Z)
    T
    Z
    可以是任何东西)时,在定义的主体中,既然
    Z
    已经被右值引用传递,我到底为什么要使用
    std::move(Z)

    您必须理解,
    std::move
    不会移动任何东西,而是将其参数“标记”为右值引用。从技术上讲,它将类型转换为右值引用。然后,由相应的移动构造函数或移动赋值运算符移动的右值引用。对于仅包含具有普通移动因子/赋值运算符的成员的对象,移动因子/赋值运算符是普通的,只是复制。通常,对象的move-ctor/assignment操作符调用其所有成员的move-ctor/assignment操作符

    所以,每当你写信的时候

    int x = 10; int y = std::move(x); 这是不同的。
    moved\u s
    的move构造函数启动,并“窃取”(即交换内部指针等)
    s
    的资源,因为后者是右值引用。最后,
    s
    将不包含任何元素

  • B
    是对象的名称。一旦一个引用被绑定,它就会命名一个对象。“右值引用”、“左值引用”和“命名对象”之间的区别仅适用于在达到这一步之前如何绑定名称
  • B.key
    是作为此函数调用的参数提供的对象中变量的名称

  • “作废”不是移动标准术语的一部分。标准库对象移出后处于未指定状态;但这不是这里发生的事情
  • A.key=std::move(B.key)
    调用
    int
    的内置赋值定义(这是一个简单赋值,不是函数调用),它只是一个副本。因此
    B.key
    保留其值

  • 要编译
    A(B())
    B
    必须是尚未定义的类型名。(你的意思是
    A(A())
    ?如果是,那么答案是“是”)

  • 见2

  • 当您想移出
    Z.foo
    时,请使用
    std::move(Z.foo)
    ,而不是从
    Z.foo
    复制


  • 隐式生成的move构造函数/赋值运算符将移动(而不是复制)-如果我们讨论的是一个包含字符串成员变量的类,那么这个区别很重要,例如,您可以详细介绍第5项吗?例如,如果我有
    ab我可以做
    A(b)
    为什么?@user2345484关于第5项,不,您不能,您需要使用
    move
    每当您向函数传递除右值以外的任何值时。如果尝试传递左值,它将无法编译。在这个注释上面的示例中,您可以这样做,因为
    A
    很可能有一个默认的复制ctor,它将进行复制。要强制移动,请通过
    std::move(b)
    b
    转换为右值引用,然后
    a
    的移动向量将生效。@user2345484名称
    std::move
    在我看来是非常不幸的,它应该被命名为
    lvalue
    decay\u lvalue
    或其他名称,而不是
    move
    ,因为它给人一种错误的印象,即函数“执行”了一些非平凡的操作。如果查看
    std::move
    的定义,您将看到它使用了包装函数
    std::remove\u reference
    。看看后者,了解它是如何工作的。例如,在第4项的函数中,我不明白为什么要执行
    std::move(z)
    ,对于
    A(A())
    ?因为
    z
    已经作为右值引用传递,并且
    std::move(z)
    还返回右值引用。 string s = "some string"; string moved_s = std::move(s); // here we tell the compiler that we can "steal" the resource of s