移动构造函数/运算符=

时间:2010-06-27 16:59:19

标签: c++ c++11 constructor move-semantics move-constructor

我正在尝试学习C ++的新功能,即移动构造函数和赋值X::operator=(X&&),我发现interesting example但我唯一不理解但更不同意的是移动ctor中的一行和赋值运算符(在下面的代码中标记):

MemoryBlock(MemoryBlock&& other)
   : _data(NULL)
   , _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 = NULL;
   other._length = 0;//WHY WOULD I EVEN BOTHER TO SET IT TO ZERO? IT DOESN'T MATTER IF IT'S ZERO OR ANYTHING ELSE IT IS JUST A VALUE.
}

所以我的问题是:我是否必须将lenght_的值设置为零,还是可以保持不变?没有任何内存泄漏和一个表达更少的afaics。

6 个答案:

答案 0 :(得分:6)

因为“移动”对象最终仍然会被破坏,所以你必须将它保持在一致的状态。当然,具体如何取决于你的对象,在这种情况下,它显然意味着将数据指针置零并将长度设置为零。

答案 1 :(得分:0)

很明显,程序员决定长度应始终具有正确的值。如果你没有设置它,析构函数中的代码将不再打印正确的东西:

std::cout << "In ~MemoryBlock(). length = "
                << _length << ".";

答案 2 :(得分:0)

_length_data是语义相关的项目。要使对象处于一致状态,_length应始终告诉您_data指向的块中有多少内存。当_data指向100个区块时,_length应为100.当_data指向1个区块时,_length应为1.如果_data未指向对于任何事物(NULL),则_length应为0.否则,如果_data为NULL且_length为100,则您的对象处于不一致状态。当我这样做时:

for (int i = 0; i < _length; ++i)
{
  // do something with _data[i], such as:
  _data[i] = 0;
}

我不应该崩溃。如果您未能正确设置_length,它将崩溃。 真正的问题是,为什么你会故意让对象处于不一致的状态,这会导致崩溃?

答案 3 :(得分:0)

很难得到这个问题的明确答案。移动语义是新的,C ++社区仍在学习如何正确使用它。

我看到的一个合理的规则是“远离”对象必须安全地破坏并且能够被赋予新值。将_length设置为零不是满足该规则所必需的,坦率地说,我不确定int表示无效状态的值是多少;在你的情况下可能为-1?

答案 4 :(得分:0)

您正在移动数据的对象可能不是临时对象(例如,您可以使用std :: move) - 将对象置于无效状态会是不好的形式。

答案 5 :(得分:0)

将值设置为零只会暴露一致性。但是,答案实际上取决于如何使用_length来破坏对象。如果不使用length来确定是否应删除_data(当移动的对象超出范围时),那么我们可以说在移动对象时忽略_length是安全的。只需确保在任何派生类型中保持这种一致性,并确保记录您忽略_length的决定。