移动构造函数是否更改 "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
由于移动与内置类型的复制相同,x
和 y
彼此独立。所以当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,它显式地将 x
的 ptr
设置为 nullptr
这样当 x
被销毁时, y
不受影响。
will the implicitly synthesized move constructor just make this in y point to the memory that x is in?
正如 Anoop 指出的那样,它将按成员方式对要移动的源 (x
) 的每个成员调用移动构造函数到目标的成员 (y
或 this
如果你想象自己“在”那个合成的移动构造函数中)。
所以在你的例子中:
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
指向的任何对象。如果 int
是 x
“拥有”的资源(也许该资源是堆上以 0 结尾的整数字符串),那么您只是“共享”了该资源。
如果您不想“共享”它,那么您可以明确地为 Foo
编写一个移动构造函数来重置“moved-from”对象的指针,或者以某种方式标记它无效。
struct Foo {
...
Foo(Foo&& other) {
this->i = other.i;
this->ptr = other.ptr;
other.ptr = nullptr;
}
}
一般来说,最好根本不要依赖“移出”对象,即确保它们尽快被销毁。
我对 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
由于移动与内置类型的复制相同,x
和 y
彼此独立。所以当x
被销毁时y
不会受到影响。
will the synthesized move constructor set the
ptr
ofx
tonullptr
?
不,合成移动函数不会为您做那件事。它只会按成员移动数据成员。对于内置类型,这与复制相同。
if it does not do this, then the
ptr
ofx
will still point to the memory to which theptr
ofy
points, then you cannot safely destroyx
.
在这种情况下,您需要编写一个 user-defined 移动 ctor,它显式地将 x
的 ptr
设置为 nullptr
这样当 x
被销毁时, y
不受影响。
will the implicitly synthesized move constructor just make this in y point to the memory that x is in?
正如 Anoop 指出的那样,它将按成员方式对要移动的源 (x
) 的每个成员调用移动构造函数到目标的成员 (y
或 this
如果你想象自己“在”那个合成的移动构造函数中)。
所以在你的例子中:
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
指向的任何对象。如果 int
是 x
“拥有”的资源(也许该资源是堆上以 0 结尾的整数字符串),那么您只是“共享”了该资源。
如果您不想“共享”它,那么您可以明确地为 Foo
编写一个移动构造函数来重置“moved-from”对象的指针,或者以某种方式标记它无效。
struct Foo {
...
Foo(Foo&& other) {
this->i = other.i;
this->ptr = other.ptr;
other.ptr = nullptr;
}
}
一般来说,最好根本不要依赖“移出”对象,即确保它们尽快被销毁。