-1

I'm trying to learn about new feature of C++ namely move constructor and assignment X::operator=(X&&) and I found interesting example but the only thing I quite not even understand but more dissagree is one line in move ctor and assignment operator (marked in the code below):

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.
}

So my question is: do I have to set the value of lenght_ to zero or can I leave it untouched? There won't be any memory-leak and one expression less afaics.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
There is nothing we can do
  • 23,727
  • 30
  • 106
  • 194
  • Maybe [this answer](http://stackoverflow.com/questions/3106110/can-someone-please-explain-move-semantics-to-me/3109981#3109981) also helps... – fredoverflow Jun 27 '10 at 20:49
  • Few minor details I wish to correct. Firstly, as this constructor is initialising _data and _length and then copying to them, it should just initialise with the correct values. I wouldn't say that `other.data = NULL` is 'releasing', it is more like 'unsetting', no memory is released. Also, you should use 'nullptr' rather than 'NULL', roughly the same, but 'nullptr' is *proper* C++. It is also advisable to avoid using `std::endl`, it makes your program stop as it waits for the output to be flushed. Unless you need that functionality, prefer `"\n"`. – thecoshman Jul 02 '13 at 13:50

6 Answers6

6

Because the "moved from" object is still going to be destructed eventually, so you have to leave it in a consistent state. Exactly how you do this depends on your object, of course, and in this case it apparently means nulling out the data pointer and setting the length to zero.

Terry Mahaffey
  • 11,775
  • 1
  • 35
  • 44
0

Setting the value to zero will only expose consistency. However, the answer really depends on how intend to use _length for the destruction of the object. If length is not used to determine if _data should be deleted (when the moved object falls out of scope), then we can say it is safe to ignore _length when moving the object. Just make sure you keep this consistency in any derived types, and make sure that your decision to ignore _length is documented.

zackery.fix
  • 1,786
  • 2
  • 11
  • 20
0

Appearantly, the programmer decided that length should always have a correct value. If you do not set it, the code in the destructor will no longer print the correct thing:

std::cout << "In ~MemoryBlock(). length = "
                << _length << ".";
Sjoerd
  • 74,049
  • 16
  • 131
  • 175
0

_length and _data are semantically related items. For an object to be in a consistent state, _length should always tell you how much memory is in the block pointed to by _data. When _data points to 100 blocks, _length should be 100. When _data points to 1 block, _length should be 1. If _data doesn't point to anything (NULL), then _length should be 0. Otherwise, if _data is NULL and _length is 100, then your object is in an inconsistent state. When I do:

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

I should not crash. If you fail to set _length correctly, it will crash. The real question is, why would you intentionally leave the object in an inconsistent state which will lead to crashes?

Bill
  • 14,257
  • 4
  • 43
  • 55
  • but in this scenario you have correct length_ already assign in the line above. What is done in a line I'm talking about is only to nullify the tmp object so I say it again: No it doesn't matter in my opinion what the value of length_ will be. – There is nothing we can do Jun 27 '10 at 18:08
  • continue in nullified object. – There is nothing we can do Jun 27 '10 at 18:24
  • @A-ha: `other._length` is only set in one place: `other._length = 0;` Logically, your opinion is that it is OK to leave an object in an inconsistent state. I disagree. – Bill Jun 27 '10 at 19:35
  • but what is incositent about it's state without leaving length_ untouched? Nothing. And the more I think about it the more I'm convinced that even the line other._data = NULL is just for safety pourposes (just to have pointer pointed to "nothing"). – There is nothing we can do Jun 27 '10 at 20:12
  • @A-ha: if the destructor has to do something with the memory besides calling delete (such as calling the destructor on objects stored in the block) then your code will crash if `_length` is not set correctly. In this _specific_ instance the destructor only calls `delete`, and ignores the value of `_length`. However, counting on code to never change is a great source of potential errors. (For example, place the `for` loop in my answer in the destructor and watch the segfault.) – Bill Jun 27 '10 at 21:14
0

It is hard to get a definitive answer to this question. Move semantics are new and the C++ community is still learning how to use it correctly.

One reasonable rule that I saw is that the "moved away from" object must destruct safely and be able to be assigned a new value. Setting _length to zero is not necessary to satisfy that rule, and frankly I am not sure what would be a good value for an int to indicate invalid state; maybe -1 in your case?

Nemanja Trifunovic
  • 24,346
  • 3
  • 50
  • 88
0

The object you are moving the data from might not be a temporary (you may use std::move for example) - it would be bad form to leave your object in an invalid state.

DanDan
  • 10,462
  • 8
  • 53
  • 69