我刚刚从 https://msdn.microsoft.com/en-us/library/dd293665.aspx 发现了以下代码显示了如何实现 move ctor:
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0)
{
std::cout << "In MemoryBlock(MemoryBlock&&). length = "
<< other._length << ". Moving resource." << std::endl;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
}
此代码附带的问题/疑问之一是:如果类 MemoryBlock
包含某个类类型成员变量(例如 someclassvar
),并且如果成员相当大,修改后的 move ctor 中的以下行是否有效(假设此 someclassvar
没有 move ctor)?
MemoryBlock(MemoryBlock&& other)
: _data(nullptr)
, _length(0),someclassvar(other.someclassvar)
{
std::cout << "In MemoryBlock(MemoryBlock&&). length = "
<< other._length << ". Moving resource." << std::endl;
// Copy the data pointer and its length from the
// source object.
_data = other._data;
_length = other._length;
// someclassvar=other.someclassvar;
// Release the data pointer from the source object so that
// the destructor does not free the memory multiple times.
other._data = nullptr;
other._length = 0;
delete other.someclassvar;
}
这里someclassvar = other.someclassvar;
我相信这会调用复制赋值运算符,那么这种行为有效吗?另外,如果 someclassvar
同时包含 move 赋值和复制赋值,那么可能会调用哪个?
move vector 在所有此类情况下都会保持有效吗?如果没有,使用复制因子是否更好?
最佳答案
首先,在任何构造函数中,如果可能的话,您应该更喜欢在构造函数的初始值设定项列表中初始化成员。其次,在 move 构造函数中,您应该使用 std::move 来 move 可 move 的成员,或者在不可 move 的情况下复制它们:
MemoryBlock(MemoryBlock&& other)
: _data(std::move(other._data)),
_length(std::move(other._length)),
someclassvar(std::move(other._someclassvar)) {
// optionally set state of moved object
}
现在 std::move
不会 move 任何对象,而是将它们转换为右值引用。因此,由于重载解析,将会发生两件事:
- 如果要 move 的类型具有用户定义的或隐式定义的 move 构造函数,则将调用此 move 构造函数,从而将对象相应地 move 到其新主机。
- 如果要 move 的类型没有任何已定义的 move 构造函数,则将调用该类型的复制构造函数。这是因为右值引用可以绑定(bind)到 const 左值引用,因此幸运的是, move 构造函数的复制构造函数可以匹配重载决策。
现在复制分配和 move 分配或多或少是相同的。正在做:
someclassvar = other.someclassvar;
将复制分配other.someclassvar
到someclassvar
。为什么?由于过载解析规则。但是,如果您这样做:
someclassvar = std::move(other.someclassvar);
如果someclassvar
有一个 move 赋值运算符,那么出于与上面解释的相同的原因,它将被调用。另一方面,如果 someclassvar 没有 move 赋值运算符,则将调用它的赋值运算符。这里不涉及构造函数,因为该语句是一个赋值。
关于c++ - Move ctor 在所有情况下都有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36742274/