特定のクラスA
のオブジェクトの_std::vector
_があります。このクラスは自明ではなく、コピーコンストラクターand移動コンストラクターが定義されています。
_std::vector<A> myvec;
_
ベクターをA
オブジェクトで埋めると(たとえばmyvec.Push_back(a)
を使用)、コピーコンストラクターA( const A&)
を使用して新しいコピーをインスタンス化して、ベクターのサイズが大きくなります。ベクター内の要素。
クラスA
の移動コンストラクターが代わりに使用されていることを何らかの方法で強制できますか?
noexcept
を使用して、移動コンストラクターとデストラクターがスローしないことをC++(具体的にはstd::vector
)に通知する必要があります。次に、ベクトルが大きくなると、移動コンストラクターが呼び出されます。
これは、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...
}
コンストラクタがnoexcept
でない場合、std::vector
はコンストラクタを使用できません。標準で要求される例外保証を保証できないためです。
標準の記述について詳しくは、 C++ Moveのセマンティクスと例外 を参照してください。
例外と関係があるかもしれないとほのめかしたBoに感謝します。また、Kerrek SBのアドバイスを考慮し、可能であればemplace_back
を使用してください。 canは高速ですが(多くの場合高速ではありません)、より明確でコンパクトになりますが、いくつかの落とし穴もあります(特に非明示的なコンストラクターの場合)。
Edit、多くの場合、デフォルトはあなたが望むものです:移動可能なものをすべて移動し、残りをコピーします。それを明示的に要求するには、
A(A && rhs) = default;
そうすることで、可能であればnoexceptを取得できます。 デフォルトのMoveコンストラクターはnoexceptとして定義されていますか?
Visual Studio 2015以前の初期バージョンでは、移動セマンティクスがサポートされていますが、これはサポートされていません。
興味深いことに、gcc 4.7.2のベクトルは、移動コンストラクターとデストラクターの両方が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
_
ただし、~foo()
からnoexcept
を削除すると、結果が異なります。
_copy
copy
copy
_
これも この質問 に答えると思います。