Переместить конструктор / оператор = - PullRequest
0 голосов
/ 27 июня 2010

Я пытаюсь узнать о новой функции C ++, а именно о конструкторе перемещения и назначении X::operator=(X&&), и нашел интересный пример , но единственное, чего я совсем не понимаю, но более несогласная, это одна строка в движении оператор и оператор присваивания (помеченный в коде ниже):

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_ на ноль или я могу оставить его без изменений? Не будет никакой утечки памяти и ни одного выражения, менее примечательного.

Ответы [ 6 ]

6 голосов
/ 27 июня 2010

Поскольку «перемещенный» объект все равно будет разрушен, вы должны оставить его в согласованном состоянии.Как именно вы это сделаете, конечно, зависит от вашего объекта, и в этом случае это, очевидно, означает обнуление указателя данных и установку длины в ноль.

0 голосов
/ 07 октября 2012

Установка значения в ноль будет только представлять согласованность.Тем не менее, ответ на самом деле зависит от того, как намерены использовать _length для уничтожения объекта.Если длина не используется для определения необходимости удаления _data (когда перемещенный объект выпадает из области видимости), то можно сказать, что при перемещении объекта можно игнорировать _length.Просто убедитесь, что вы сохраняете эту согласованность в любых производных типах, и убедитесь, что ваше решение игнорировать _length задокументировано.

0 голосов
/ 27 июня 2010

Объект, с которого вы перемещаете данные, может не быть временным (например, вы можете использовать std :: move) - было бы неправильно оставлять ваш объект в недействительном состоянии.

0 голосов
/ 27 июня 2010

Трудно получить окончательный ответ на этот вопрос. Семантика Move является новой, и сообщество C ++ все еще учится правильно ее использовать.

Одно разумное правило, которое я видел, состоит в том, что «отодвинутый» объект должен безопасно разрушаться и иметь возможность назначать новое значение. Установка _length в ноль не обязательна для удовлетворения этого правила, и, честно говоря, я не уверен, что было бы хорошим значением для int, чтобы указать недопустимое состояние; возможно -1 в твоем случае?

0 голосов
/ 27 июня 2010

_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, произойдет сбой. На самом деле вопрос в том, почему вы намеренно оставляете объект в несовместимом состоянии, что приведет к сбоям?

0 голосов
/ 27 июня 2010

Очевидно, программист решил, что длина всегда должна иметь правильное значение. Если вы не установите его, код в деструкторе больше не будет печатать правильную вещь:

std::cout << "In ~MemoryBlock(). length = "
                << _length << ".";
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...