0

我在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);

    }

有人可以给我一些例子(最有用的情况),该类中的移动构造函数采取行动吗?
我理解这种构造函数的目的,但我无法确定它何时会在实际应用程序中使用。

4

2 回答 2

0

此示例中未使用移动构造函数,因为a它是一个左值。然而,如果你有一个函数返回一个ArrayWrapper, ie ArrayWrapper func(),那么它的函数调用的结果将是一个右值,因此当你这样做时会使用移动构造函数ArrayWrapper b(func())

这可能是一个好的开始:http ://thbecker.net/articles/rvalue_references/section_01.html

于 2013-07-11T07:05:17.660 回答
0
void do_something_complex( ArrayWrapper data );

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

此处对函数的调用将创建一个临时 ArrayWrapper,其数据将在函数内部移动而不是复制,这意味着只需设置一个指针,而不必将临时数据中的所有数据复制到函数内部参数中。

这是一个更常见的变体:

ArrayWrapper generate_random_data( int seed );

void do_something_complex( ArrayWrapper data );

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

同样的事情发生了:generate 函数返回的数据被移动(使用移动构造函数),而不是复制,在 do something 函数参数内。

进一步澄清:

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

这里可能发生两件事。首先,将使用移动构造函数将返回的对象传递到函数外部,不需要使用指针或类似的东西(如果没有移动构造函数,将使用复制构造函数代替)。其次,可选地,如果您有:

ArrayWrapper a = generate_random_data( 42 );

然后大多数编译器将生成一个称为 NRVO 的授权优化,基本上是返回的对象将在外部分配的对象内部构造,这里是“a”。

这意味着如果可以,编译器将避免移动和复制构造。如果两者都无法避免,它会在确定对象不会比移动更远时尝试移动对象。如果不能保证这一点,那么它将使用副本。

于 2013-07-11T07:12:53.247 回答