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
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 );
}

ここで 2 つのことが起こります。まず、移動コンストラクターを使用して、返されたオブジェクトを関数の外に渡します。ポインターなどを使用する必要はありません (移動コンストラクターがない場合は、代わりにコピー コンストラクターが使用されます)。次に、オプションで、次の場合:

ArrayWrapper a = generate_random_data( 42 );

次に、ほとんどのコンパイラは NRVO と呼ばれる承認された最適化を生成します。これは基本的に、返されたオブジェクトが外部割り当てオブジェクト (ここでは「a」) 内に構築されるというものです。

これは、可能な場合、コンパイラは移動とコピーの両方の構築を回避することを意味します。両方を回避できない場合、オブジェクトがその移動より先に存続しないことが確実な場合に、オブジェクトの移動を試みます。それが保証できない場合は、コピーを使用します。

于 2013-07-11T07:12:53.247 に答える
0

aは左辺値であるため、この例では move コンストラクターは使用されません。ただし、 を返す関数ArrayWrapper、つまりArrayWrapper func()がある場合、その関数呼び出しの結果は右辺値になるため、その場合はムーブ コンストラクターが使用されますArrayWrapper b(func())

これは良いスタートかもしれません: http://thbecker.net/articles/rvalue_references/section_01.html

于 2013-07-11T07:05:17.660 に答える