移动构造函数和 std::move 混淆

move constructor and std::move confusion

本文关键字:move 混淆 std 构造函数 移动      更新时间:2023-10-16

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

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);}
};
  1. 我以为B是一个右值引用,为什么你可以std::move应用于 ravlue 引用的成员?
  2. B.keyB.value被移动后,两者都无效,但作为类A的对象如何B失效?
  3. 如果我有A a(A())A()显然是 rvlaue,A()会被std::move感动吗,为什么?
  4. 同样,如果我有一个函数

    int add(int && z){ int x = std:move(z); int y = std:move(z); return x+y; }

如果我打电话给add(5)5怎么能被移动,为什么?请注意,z已经移动了两次,z第一次移动后,它已经失效了,你怎么能再次移动它呢?

  1. 在定义foo (T && Z )(TZ可以是任何东西(时,在定义的正文中,为什么我应该使用std::move(Z),因为Z已经被右值引用传递了,什么时候应该使用std::move

std::move 不会移动任何内容,而是将其参数"标记"为右值引用。从技术上讲,它将类型转换为右值引用。然后,右值引用它由相应的移动构造函数或移动赋值运算符移动。对于仅包含具有简单移动 ctors/赋值运算符的成员的对象,移动 ctor/赋值运算符是微不足道的,只是复制。通常,对象的移动 ctor/赋值运算符调用其所有成员的移动 ctor/赋值运算符。

所以,每当你写

整数 x = 10;int y = std::move(x(;

在赋值y = std::move(x)的右侧,您有一个类型为 int&& 的右值引用。但是,int没有非平凡的移动ctor,并且简单地将右值复制到y中,x中没有任何变化。

另一方面

字符串 s = "某个字符串";字符串 moved_s = 标准::移动;在这里我们告诉编译器我们可以"窃取"s 的资源

是不同的。moved_s的移动构造函数启动并"窃取"(即交换内部指针等(s的资源,因为后者是右值引用。最后,s将不包含任何元素。

  1. B是对象的名称。绑定引用后,它将命名一个对象。"右值引用"、"左值引用"和"命名对象"的区别仅适用于在您走到这一步之前如何绑定名称。

B.key 是对象中作为参数提供给此函数调用的变量的名称。

  1. "无效"不是搬家标准术语的一部分。标准库对象在移出后将处于未指定状态;但这不是这里发生的事情。

A.key = std::move(B.key)行调用int赋值的内置定义(这是简单的赋值,而不是函数调用(,这只是一个副本。所以B.key保留了它的价值。

  1. 要进行A(B())编译,B必须是尚未定义的类型名。(你是说A(A())?如果是这样,那么答案是"是"(。

  2. 见2

  3. 每当您想要移出Z.foo而不是从Z.foo复制

  4. 时,请使用 std::move(Z.foo)