我正在尝试学习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。
答案 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的决定。