標準コンテナでstd::auto_ptr<>
を使用するのはなぜ間違っているのですか?
C++標準では、STL要素は「コピー構築可能」かつ「割り当て可能」でなければならないとされています。つまり、要素は割り当てまたはコピーできる必要があり、2つの要素は論理的に独立しています。 std::auto_ptr
はこの要件を満たしていません。
たとえば、次のコードをご覧ください。
class X
{
};
std::vector<std::auto_ptr<X> > vecX;
vecX.Push_back(new X);
std::auto_ptr<X> pX = vecX[0]; // vecX[0] is assigned NULL.
この制限を克服するには、 std::unique_ptr
、 std::shared_ptr
または std::weak_ptr
スマートポインターまたはC++ 11がない場合の同等のブースト。 これらのスマートポインターのBoostライブラリドキュメントを以下に示します。
auto_ptr
のコピーセマンティクスは、コンテナと互換性がありません。
具体的には、1つのauto_ptr
を別のauto_ptr
にコピーしても、ポインターの所有権が失われるため、2つの等しいオブジェクトは作成されません。
より具体的には、-CODE--をコピーすると、コピーの1つがポインターを離します。これらのどれがコンテナに残っているかは定義されていません。したがって、コンテナにauto_ptrs
を格納すると、ポインタへのアクセスがランダムに失われる可能性があります。
このテーマに関する2つの非常に優れた記事:
STLコンテナーは、保管するアイテムをコピーできる必要があり、オリジナルとコピーが同等になることを期待するように設計されています。自動ポインタオブジェクトは完全に異なるコントラクトを持っているため、コピーにより所有権の譲渡が作成されます。これは、auto_ptrのコンテナーが使用法に応じて奇妙な動作を示すことを意味します。
Effective STL(Scott Meyers)アイテム8には何がうまくいかないかについての詳細な説明があり、Effective C++(Scott Meyers)アイテム13にはそれほど詳細ではない説明もあります。
STLコンテナには、含まれるアイテムのコピーが保存されます。 auto_ptrをコピーすると、古いptrがnullに設定されます。この動作により、多くのコンテナメソッドが破損します。
C++ 03標準(ISO-IEC 14882-2003)は20.4.5段落3で述べています:
[...] [注:[...] auto_ptrは、標準ライブラリコンテナ要素のCopyConstructibleおよびAssignable要件を満たしていないため、auto_ptrを使用して標準ライブラリコンテナをインスタンス化すると、未定義の動作が発生します。 —終了ノート]
C++ 11標準(ISO-IEC 14882-2011)は、付録D.10.1段落3に記載されています:
[...]注:[...] auto_ptrのインスタンスは、MoveConstructibleおよびMoveAssignableの要件を満たしますが、CopyConstructibleおよびCopyAssignableの要件を満たしません。 —終了ノート]
C++ 14標準(ISO-IEC 14882-2014)付録C.4.2付録D:互換機能:
Change:クラステンプレートauto_ptr、unary_function、binary_function、関数テンプレートrandom_shuffle、および関数テンプレート(およびそれらの戻り値型)ptr_fun、mem_fun、mem_fun_ref、bind1st、bind2ndは定義されていません。
根拠:新しい機能に置き換えられました。
元の機能への影響:これらのクラステンプレートと関数テンプレートを使用する有効なC++ 2014コードは、この国際標準でコンパイルに失敗する。