移动构造函数是否更改 "this" 指向的内存?

Does move constructor change the memory to which "this" points to?

我对 C++ 移动构造函数有些困惑。如果编译器隐式合成一个移动构造函数,这个移动构造函数会做什么?它会让“this”指向用于初始化的对象吗? 有一个例子:

struct Foo {
    int i;
    int *ptr;
};

Foo x;
Foo y(std::move(x));

隐式合成的移动构造函数是否只会使 y 中的 this 指向 x 所在的内存?如果是这样,如何保证x移动后可破坏(如果x被破坏,y中的成员是否有效)?如果不是,y 的移动构造函数如何工作?

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

合成移动函数memberwise-move其数据成员正在创建的对象(此处为y)的参数(此处为x)。

此外,请注意对于 built-in 类型,如 int,移动与复制相同。


how to ensure that x is destructible after the move

由于移动与内置类型的复制相同,xy 彼此独立。所以当x被销毁时y不会受到影响。


will the synthesized move constructor set the ptr of x to nullptr?

不,合成移动函数不会为您做那件事。它只会按成员移动数据成员。对于内置类型,这与复制相同。


if it does not do this, then the ptr of x will still point to the memory to which the ptr of y points, then you cannot safely destroy x.

在这种情况下,您需要编写一个 user-defined 移动 ctor,它显式地将 xptr 设置为 nullptr 这样当 x 被销毁时, y 不受影响。

will the implicitly synthesized move constructor just make this in y point to the memory that x is in?

正如 Anoop 指出的那样,它将按成员方式对要移动的源 (x) 的每个成员调用移动构造函数到目标的成员 (ythis如果你想象自己“在”那个合成的移动构造函数中)。

所以在你的例子中:

  • int x.i 将移动到 y.i (this->i)
  • int* x.ptr 将移动到 y.ptr (this->ptr)。

请注意,这些特定的移动将通过复制来执行。

how to ensure that x is destructible after the move (if x is destroyed, will members in y be valid)?

它总是可以被破坏的。至于它是否“有效”,这取决于。默认移动结构实际上是一个副本。现在有两个对象指向 x.ptr 指向的任何对象。如果 intx“拥有”的资源(也许该资源是堆上以 0 结尾的整数字符串),那么您只是“共享”了该资源。

如果您不想“共享”它,那么您可以明确地为 Foo 编写一个移动构造函数来重置“moved-from”对象的指针,或者以某种方式标记它无效。

struct Foo {
  ...
  Foo(Foo&& other) {
    this->i = other.i;
    this->ptr = other.ptr;
    other.ptr = nullptr;
  }
}

一般来说,最好根本不要依赖“移出”对象,即确保它们尽快被销毁。