web-dev-qa-db-ja.com

標準コンテナでstd :: auto_ptr <>を使用するのはなぜ間違っているのですか?

標準コンテナでstd::auto_ptr<>を使用するのはなぜ間違っているのですか?

205
Uhall

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_ptrstd::shared_ptr または std::weak_ptr スマートポインターまたはC++ 11がない場合の同等のブースト。 これらのスマートポインターのBoostライブラリドキュメントを以下に示します。

123
Kevin

auto_ptrコピーセマンティクスは、コンテナと互換性がありません。

具体的には、1つのauto_ptrを別のauto_ptrにコピーしても、ポインターの所有権が失われるため、2つの等しいオブジェクトは作成されません。

より具体的には、-CODE--をコピーすると、コピーの1つがポインターを離します。これらのどれがコンテナに残っているかは定義されていません。したがって、コンテナにauto_ptrsを格納すると、ポインタへのアクセスがランダムに失われる可能性があります。

65
Frank Krueger

このテーマに関する2つの非常に優れた記事:

38
Lazer

STLコンテナーは、保管するアイテムをコピーできる必要があり、オリジナルとコピーが同等になることを期待するように設計されています。自動ポインタオブジェクトは完全に異なるコントラクトを持っているため、コピーにより所有権の譲渡が作成されます。これは、auto_ptrのコンテナーが使用法に応じて奇妙な動作を示すことを意味します。

Effective STL(Scott Meyers)アイテム8には何がうまくいかないかについての詳細な説明があり、Effective C++(Scott Meyers)アイテム13にはそれほど詳細ではない説明もあります。

17
Garth Gilmour

STLコンテナには、含まれるアイテムのコピーが保存されます。 auto_ptrをコピーすると、古いptrがnullに設定されます。この動作により、多くのコンテナメソッドが破損します。

12
Dustin Getz

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コードは、この国際標準でコンパイルに失敗する。

4
bitek