3

なぜこれを行わないのですか:(vs2010)クラス内でベクトルを移動しますか?

#include <vector>

class MoveTest
{
public:
    std::vector<int> m_things;
};

int _tmain(int argc, _TCHAR* argv[])
{
    MoveTest m;
    m.m_things.push_back(12);

    MoveTest m2 = std::move(m);
    // std::vector has been copied, not moved

    return 0;
}

これは、std :: vector(およびその他の移動可能なクラス)を使用するすべてのクラスに、明示的な移動コンストラクターと割り当てが必要であることを意味しますか?

4

4 に答える 4

9

vs2010 が出荷されたときと比較して、これらのルールの遅れに関して既に与えられた適切な回答に加えて、

暗黙的に生成されたムーブ コンストラクターのルールは次のとおりです。

クラス X の定義でムーブ コンストラクターが明示的に宣言されていない場合、1 つが暗黙的にデフォルトとして宣言されます。

  • X にはユーザー宣言のコピー コンストラクターがありません。
  • X には、ユーザー宣言のコピー代入演算子がありません。
  • X には、ユーザー宣言の移動代入演算子がありません。
  • X にはユーザー宣言のデストラクタがありません。
  • 移動コンストラクターは、暗黙的に削除済みとして定義されません。

暗黙的に生成された移動代入演算子の規則は、上記のパターンに従います。

コピー コンストラクターが暗黙的に生成される場合のルールが少し変更されました。

クラス定義でコピー コンストラクターが明示的に宣言されていない場合は、暗黙的に宣言されます。クラス定義でムーブ コンストラクターまたはムーブ代入演算子が宣言されている場合、暗黙的に宣言されたコピー コンストラクターは削除済みとして定義されます。それ以外の場合は、デフォルト (8.4) として定義されます。クラスにユーザー宣言のコピー代入演算子またはユーザー宣言のデストラクタがある場合、後者のケースは推奨されません。

コピー代入演算子についても同様です。

クラス定義でコピー代入演算子が明示的に宣言されていない場合は、暗黙的に宣言されます。クラス定義でムーブ コンストラクターまたはムーブ代入演算子が宣言されている場合、暗黙的に宣言されたコピー代入演算子は削除済みとして定義されます。それ以外の場合は、デフォルト (8.4) として定義されます。クラスにユーザー宣言のコピー コンストラクターまたはユーザー宣言のデストラクタがある場合、後者のケースは推奨されません。

結論: 3 のルールは 5 のルールになりました。5 つすべてを無視するか (デフォルトの動作がうまくいく場合)、または 5 つすべてについて考える (そしておそらく定義する) 必要があります。

  1. コピーコンストラクター
  2. 課題のコピー
  3. 移動コンストラクタ
  4. 割り当てを移動
  5. デストラクタ
于 2011-05-12T11:32:40.467 に答える
7

完全に準拠した C++0x コンパイラを使用すると、クラスには暗黙的なコピー コンストラクターだけでなく、メンバーを移動する暗黙的な移動コンストラクターも含まれます。したがって、この例では、暗黙的な移動コンストラクターが使用されます。

ただし、MSVC2010 は、この規則が委員会によって合意される前に公開されたため、ムーブ コンストラクターを明示的に記述する必要があります。次に、デフォルトのコンストラクターとコピー コンストラクターも定義する必要があります。おそらく、適切な手段として、move-assignment と copy-assignment も定義する必要があります。

class MoveTest
{
public:
    std::vector<int> m_things;

    MoveTest()
    {}

    MoveTest(MoveTest&& other):
        m_things(std::move(other.m_things))
    {}

    MoveTest(MoveTest const& other):
        m_things(other.m_things)
    {}

    MoveTest& operator=(MoveTest&& other)
    {
        MoveTest temp(std::move(other));
        std::swap(*this,temp);
        return *this;
    }

    MoveTest& operator=(MoveTest const& other)
    {
        if(&other!=this)
        {
            MoveTest temp(other);
            std::swap(*this,temp);
        }
        return *this;
    }

};
于 2011-05-12T10:50:46.487 に答える
2

このMoveTestクラスには移動コンストラクターがないため、既定のコピー コンストラクターが使用されました。

コピー コンストラクターは、メンバー要素をコピーします。:-)

C++11 準拠コンパイラがデフォルトの move コンストラクターを生成する場合があるかもしれませんが、最終的なルールがどこにあるのかはわかりません (非常に遅い変更がありました)。VS2010は古すぎてそれについても知ることができません。

于 2011-05-12T09:55:08.880 に答える
1

VS2010 には、暗黙的な移動コンストラクターがありません。明示的に記述する必要があります。

于 2011-05-12T10:06:01.723 に答える