Reputation: 101
// move constructor
ArrayWrapper (ArrayWrapper&& other)
: _p_vals( other._p_vals )
, _size( other._size )
{
other._p_vals = NULL;
other._size = 0;
}
I found a tutorial on rvalue references. I don't really understand why we have to set other._p_vals = NULL;
and other._size = 0;
The author explains:
But why do we need to set other._p_vals = NULL? The reason is the destructor--when the temporary object goes out of scope, just like all other C++ objects, its destructor will run.
If it does go out of scope and gets destroyed why bother setting other._p_vals = NULL
When its destructor runs, it will free _p_vals. The same _p_vals that we just copied!
I thought we moved not copied, or... am I wrong?
If we don't set other._p_vals to NULL, the move would not really be a move--it would just be a copy that introduces a crash later on once we start using freed memory. This is the whole point of a move constructor: to avoid a copy by changing the original, temporary object!
Can someone help me understand?!?
Upvotes: 4
Views: 102
Reputation: 19767
Since this class contains a raw pointer, we can only assume it owns it, and therefore its destructor must look something like:
ArrayWrapper::~ArrayWrapper() {
delete[] _p_vals;
}
In this move constructor we are "stealing" the internals of other
. If we don't blank out the internals of other
(being careful to leave it in a consistent "empty" state, so also setting _size = 0
), then when either of other
or the new object is destroyed, the one that remains will be pointing at some data that has now been deleted.
Sharing internals is a very different pattern to stealing someone else's internals.
Upvotes: 4