102

std::vector特定のクラスのオブジェクトがありますA。クラスは自明ではなく、コピー コンストラクタームーブ コンストラクターが定義されています。

std::vector<A>  myvec;

ベクトルをAオブジェクトで満たすと (例: を使用myvec.push_back(a))、ベクトルのサイズが大きくなり、コピー コンストラクターを使用してA( const A&)、ベクトル内の要素の新しいコピーをインスタンス化します。

Aクラスのムーブコンストラクターが代わりに使用されていることをどうにかして強制できますか?

4

3 に答える 3

143

std::vectorを使用して、移動コンストラクタとデストラクタがスローしないことを C++ (具体的には ) に通知する必要がありますnoexcept。次に、ベクターが大きくなると移動コンストラクターが呼び出されます。

これは、によって尊重される移動コンストラクターを宣言および実装する方法ですstd::vector

A(A && rhs) noexcept { 
  std::cout << "i am the move constr" <<std::endl;
  ... some code doing the move ...  
  m_value=std::move(rhs.m_value) ; // etc...
}

コンストラクターが でない場合は、標準で要求される例外保証を保証できないため、使用できませんnoexceptstd::vector

標準で述べられていることの詳細については、 C++ Move のセマンティクスと例外を参照してください。

例外に関係している可能性があることをほのめかした Bo の功績です。また、可能な場合は Kerrek SB のアドバイスと使用を検討してくださいemplace_back。高速化できますが (多くの場合そうではありません)、より明確でコンパクトになりますが、いくつかの落とし穴もあります (特に非明示的なコンストラクターの場合)。

Edit、多くの場合、デフォルトはあなたが望むものです:移動できるものはすべて移動し、残りはコピーします。それを明示的に求めるには、次のように記述します。

A(A && rhs) = default;

そうすることで、可能な場合は noexcept が得られます:デフォルトの Move コンストラクターは noexcept として定義されていますか?

Visual Studio 2015 以前の初期バージョンでは、移動セマンティクスがサポートされていても、これはサポートされていないことに注意してください。

于 2012-01-14T19:50:00.577 に答える
17

興味深いことに、gcc 4.7.2のベクトルは、moveコンストラクタとデストラクタの両方がである場合にのみmoveコンストラクタを使用しますnoexcept。簡単な例:

struct foo {
    foo() {}
    foo( const foo & ) noexcept { std::cout << "copy\n"; }
    foo( foo && ) noexcept { std::cout << "move\n"; }
    ~foo() noexcept {}
};

int main() {
    std::vector< foo > v;
    for ( int i = 0; i < 3; ++i ) v.emplace_back();
}

これにより、期待値が出力されます。

move
move
move

noexceptただし、から削除する~foo()と、結果は異なります。

copy
copy
copy

これもこの質問に答えると思います。

于 2013-03-14T19:12:50.193 に答える