7

別の質問で、移動コンストラクターを実装する場合、初期化子リストの各メンバーを std::move することをお勧めします。これは、メンバーが別のオブジェクトである場合、そのオブジェクトの移動コンストラクターが呼び出されるためです。そのようです...

//Move constructor
Car::Car(Car && obj)
    : 
    prBufferLength(std::move(obj.prBufferLength)), 
    prBuffer(std::move(obj.prBuffer)) 
{
    obj.prBuffer = nullptr;
    obj.prBufferLength = 0;
}

ただし、私が見たすべての移動代入演算子のサンプルでは、​​同じ理由で std::move を使用することについて言及されていません。メンバーがオブジェクトの場合、std::move を使用する必要がありますか? そのようです...

//Move assignment
Car Car::operator=(Car && obj)  
{
    delete[] prBuffer;

    prBufferLength = std::move(obj.prBufferLength);
    prBuffer = std::move(obj.prBuffer);

    obj.prBuffer = nullptr;
    obj.prBufferLength = 0;
    return *this;
}

アップデート:

私が選択した例では std::move を使用する必要がないことを感謝します (不十分) が、メンバーがオブジェクトであるかどうかに興味があります。

4

5 に答える 5

3

リンクされた質問を読んだ後、2番目に賛成の回答のアドバイスstd::moveは、プリミティブ型であるかどうかに関係なく、正しいことを行うため、moveコンストラクターの初期化子リストで使用することです。私はそれに少し同意せず、適切な場合にのみ電話をかけるべきだと思いますstd::moveが、これは個人的な好みでした。

std::moveまた、ムーブ代入演算子の場合、不要な呼び出しは個人的に削除する必要があると思いますが、その方法は問題ありません。別のオプションはstd::swap、あなたのために正しいことをするものを使用することです。

Car Car::operator=(Car && obj)  
{
    std::swap(this->prBufferLength, obj.prBufferLength);
    std::swap(this->prBuffer, obj.prBuffer); 
    return *this;
}

上記のムーブ代入演算子とムーブ代入演算子の違いは、バージョンがメモリの割り当てをすぐに解除している間、メモリの割り当て解除が遅れることです。これは、状況によっては重要な場合があります。

于 2012-11-15T21:05:07.643 に答える
1

prBufferポインタのように見えprBufferLength、ある種の整数型であるためmove、この特定のケースではどちらも基本型であるため、違いはありません。

たとえばprBufferstd::stringを使用moveして、ムーブ コンストラクターまたはムーブ代入演算子の使用を強制する必要があります。

于 2012-11-15T20:43:10.297 に答える
1

メンバー オブジェクトを移動することでメリットが得られる場合は、確実に移動する必要があります。リンク先の回答で示された別の戦略は、スワッピングです。スワッピングは移動に似ていますが、両方向に移動しています。クラスがリソースを管理する場合、渡されたオブジェクト (右辺値) が不要になったデータを受け取るという効果があります。そのデータは、そのオブジェクトのデストラクタによって破棄されます。たとえば、移動代入演算子は次のように記述できます。

Car Car::operator=(Car && obj)  
{
    // don't need this, it will be handled by obj's destructor
    // delete[] prBuffer; 

    using std::swap;
    swap(prBuffer, obj.prBuffer);
    swap(prBufferLength, obj.prBufferLength);

    return *this;
}

Copy-and-Swapイディオムも見てください。これにより、移動とコピーの両方に同じ代入演算子を使用できますが、自己代入により不要なコピーが発生するというわずかな欠点があります。

于 2012-11-15T21:04:31.477 に答える
1

C++ や人生の多くのことと同様に、質問に対する決定的な「はい」または「いいえ」の答えはありません。

つまり、一般的なルールとして、着信メンバーがクリア/リセット/空になり、着信メンバーを宛先メンバーに割り当てると代入演算子が呼び出される場合は、移動代入がコピー代入演算子の代わりに演算子が呼び出されます。

代入演算子が呼び出されない場合 (つまり、浅いコピーが行われるだけの場合)、std::move を使用する必要はありません。

于 2012-11-15T20:48:43.490 に答える
0

移動代入を実装する (?) より良い方法は、移動コンストラクターを使用して新しい一時オブジェクトを作成し、コピー代入と同様に現在のオブジェクトと交換することだと思います。

コードの重複を避けるだけでなく、メンバーの移動を忘れるなどの誤ったミスを防ぐこともできます。

于 2012-11-15T21:00:53.137 に答える