Samu
Samu

Reputation: 101

rvalue references in C++

   // 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

Answers (1)

BoBTFish
BoBTFish

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

Related Questions