0

I found this example on http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html

   #include <iostream>
    using namespace std;

class ArrayWrapper
    {
    public:
        // default constructor produces a moderately sized array
        ArrayWrapper ()
            : _p_vals( new int[ 64 ] )
            , _size( 64 )
        {}

        ArrayWrapper (int n)
            : _p_vals( new int[ n ] )
            , _size( n )
        {}

        // move constructor
        ArrayWrapper (ArrayWrapper&& other)
            : _p_vals( other._p_vals  )
            , _size( other._size )
        {
            cout<<"move constructor"<<endl;
            other._p_vals = NULL;
        }

        // copy constructor
        ArrayWrapper (const ArrayWrapper& other)
            : _p_vals( new int[ other._size  ] )
            , _size( other._size )
        {
            cout<<"copy constructor"<<endl;
            for ( int i = 0; i < _size; ++i )
            {
                _p_vals[ i ] = other._p_vals[ i ];
            }
        }
        ~ArrayWrapper ()
        {
            delete [] _p_vals;
        }

    private:
        int *_p_vals;
        int _size;
    };

    int main()
    {   
            ArrayWrapper a(20);
            ArrayWrapper b(a);

    }

Could someone give me some examples (the most useful situations) where the move constructor inside that class takes action?
I understood the aim of this kind of constructor, but I cannot identify when exactly it will be used in a real application.

R. Martinho Fernandes
  • 228,013
  • 71
  • 433
  • 510
Hélène
  • 377
  • 1
  • 5
  • 13

2 Answers2

0

The move constructor is not used in this example, since a is an lvalue. If however you had a function returning an ArrayWrapper, i.e. ArrayWrapper func(), then the result of its function call would be an rvalue, thus the move constructor is used when you do ArrayWrapper b(func()).

This might be a good start: http://thbecker.net/articles/rvalue_references/section_01.html

filmor
  • 30,840
  • 6
  • 50
  • 48
0
void do_something_complex( ArrayWrapper data );

int main()
{
   do_something_complex( ArrayWrapper( 42 ) );
}

Here the call to the function will create a temporary ArrayWrapper which data will be moved inside the function instead of copied, which mean only a pointer will be set instead of having to duplicate all the data from the temporary into the function internal parameter.

Here is a more usual variant:

ArrayWrapper generate_random_data( int seed );

void do_something_complex( ArrayWrapper data );

int main()
{
   do_something_complex( generate_random_data( 42 ) );
}    

The same thing happen: the data returned by the generate function is moved (using the move constructor), not copied, inside the do something function parametter.

To clarify further:

ArrayWrapper generate_random_data( int seed )
{
    int random_count = random( 0, 42, seed ); // lets say this work
    return ArrayWrapper( seed );
}

Here two thing can happen. First, the move constructor will be used to pass the returned object outside the function, no need to use a pointer or something similar (if there is no move constructor, the copy constructor will be used instead). Second, optionally, if you have:

ArrayWrapper a = generate_random_data( 42 );

Then most compilers will generate an authorized optimization called NRVO which basically is that the returned object will be constructed inside the external assigned object, here 'a'.

This mean that if it can, the compiler will avoid both move and copy construction. If it can't avoid both, it will try moving objects when it's certain the object will not live further than the move. If it can't be assured of that, then it will use the copy.

Klaim
  • 67,274
  • 36
  • 133
  • 188
  • Apparently it doesn't call the move constructor. Only the second constructor. – Hélène Jul 11 '13 at 07:22
  • @iulian Which part are you talking about? The NRVO optimization I was talking about does avoid moving if it have to. IF you see the int constructor call but no other constructor then it avoided both moving and copying. – Klaim Jul 11 '13 at 07:44
  • OK, now I understood. I hadn't read the NRVO issue. Thanks. – Hélène Jul 11 '13 at 08:33