为什么要在移动构造函数的末尾将基元类型值设置为零

Why set primitive type value to zero in the end of move constructor function

本文关键字:类型 设置 移动 构造函数 为什么      更新时间:2023-10-16
MemoryBlock(MemoryBlock&& other)
   : _data(nullptr)
   , _length(0)
{
   std::cout << "In MemoryBlock(MemoryBlock&&). length = " 
             << other._length << ". Moving resource." << std::endl;
   _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;
}

下面是来自 Microsoft msdn 的示例。它size_t,不可能是免费的。因此,您不必将其分配给 0。为什么将other._length设置为 0?感谢

为了完整起见,据我所知没有具体的技术原因。 other在退出其作用域时将被销毁,因为您在 move 构造函数中将其定义为右值引用。

您必须确保将移动构造函数/赋值中的右值引用保留为可破坏状态,这是通过将nullptr分配给_data的情况(通常必须确保指针指向null(。_length = 0只是为了完整性(或习惯(:移动数据,数据指针为空,长度必须为零。

这样做通常是一个好主意,这样您就可以保持更严格的不变量,使类的其他部分更容易推理,并且需要更少的 if 检查。举一个具体的例子,假设 MemoryBlock 有一个返回 length 的 length(( 方法。如果您没有在移动时设置_length,则此 length(( 方法将需要 if 检查_data不为 null。通过在移动后将其设置为零,此方法可以简单地返回_length。

将对象 A 的内容移动到另一个对象 B 后,A 仍然存在。 它将在范围结束时被销毁,同时可以再次使用。 你不能真正指望 A 的内容在被移动后是什么,但你可以给它分配一个新值。 例如,这是合法代码:

std::string a = "Some string";
std::cout << "a before move: " << a << endl;
std::string b = std::move(a);
std::cout << "a after move: " << a << endl;
std::cout << "b after move: " << b << endl;
a = "Some other string";
std::cout << "a after reassignment: " << a << endl;

它在Visual Studio下生成以下内容:

a before move: Some string
a after move:
b after move: Some string
a after reassignment: Some other string