std::auto_ptr<>
標準のコンテナで使用するのはなぜ間違っているのですか?
move
セマンティックで、unique_ptr
に関連する問題を回避するように設計されていauto_ptr
ます。C ++ 03では、auto_ptr
コンパイラと言語がl値とr値を区別できなかったため、一部の「ハック」を使用して目的の動作を実現するため、言語はすべてのシナリオで正しく安全に動作するクラスを作成するのに十分強力ではありませんでした。ほとんどの時間。
std::auto_ptr<>
標準のコンテナで使用するのはなぜ間違っているのですか?
move
セマンティックで、unique_ptr
に関連する問題を回避するように設計されていauto_ptr
ます。C ++ 03では、auto_ptr
コンパイラと言語がl値とr値を区別できなかったため、一部の「ハック」を使用して目的の動作を実現するため、言語はすべてのシナリオで正しく安全に動作するクラスを作成するのに十分強力ではありませんでした。ほとんどの時間。
回答:
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を持っていない場合は、スマートポインタやブースト同等物。 以下は、これらのスマートポインタに関するブーストライブラリのドキュメントです。
unique_ptr
また、コピーを許可しないため、特定のSTL操作は移動セマンティクスを使用できない限り正しく機能しません。
std::unique_ptr
そのクラステンプレートを使用する必要があります」:移動セマンティクス(その仕様では右辺値参照が必要)のためにのみ存在できるため、基本的にはC ++ 11が必要です。ただし、(および関連して)C ++ 11標準では、STL要素の型は「コピー構築可能」かつ「割り当て可能」でなければならないとはもはや言われていません。移動構成可能で、移動割り当て可能で十分です。実際、unique_ptr
インスタンスは移動構成可能であり、移動割り当て可能です。しかし、auto_ptr
インスタンスもそうです!結果として、C ++ 11では、でauto_ptr
できることを行うことができますunique_ptr
。
reset
とrelease
必要に応じて)
reset
と」でなければrelease
、コメントに何が当てはまるのかわかりません。auto_ptr
とのunique_ptr
両方にこれらのメソッドがあり、どちらの場合も同じことを行うことに注意してください。
のコピーセマンティクスはauto_ptr
コンテナと互換性がありません。
具体的には、1つauto_ptr
をポインタの所有権を失ったため、1 つを別のオブジェクトにコピーしても、2つの等しいオブジェクトは作成されません。
より具体的には、auto_ptr
原因をコピーすると、コピーの1つがポインタを離します。これらのうちどれがコンテナに残っているかは定義されていません。したがって、auto_ptrs
コンテナーに格納すると、ポインターへのアクセスがランダムに失われる可能性があります。
このテーマに関する2つの非常に優れた記事:
auto_ptr
いるなら、これらのリンクは役に立つでしょう、私は確信しています。
sort()
ここでのすべての回答よりも明確です。
STLコンテナには、含まれているアイテムのコピーが格納されます。auto_ptrをコピーすると、古いptrがnullに設定されます。この動作により、多くのコンテナメソッドが壊れます。
unique_ptr
は、適切なC ++ 11オブジェクトと同様に、移動構築または割り当て時にのみリソースの所有権を転送できます。これにより、プログラマーはlvalueを渡さず、意図せずに/予期せずそれを変異させるのでstd::move(sourceObject)
はなく、意図的または一時的に渡す必要があります。ここで徹底的に強調されているように、コピー割り当て...はの中心的な問題でした。auto_ptr
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で述べています:互換性機能:
変更:クラステンプレートauto_ptr、unary_function、binary_function、関数テンプレートrandom_shuffle、関数テンプレート(およびそれらの戻り型)ptr_fun、mem_fun、mem_fun_ref、bind1st、bind2ndは定義されていません。
理論的根拠:新しい機能に置き換えられました。
元の機能への影響:これらのクラステンプレートと関数テンプレートを使用する有効なC ++ 2014コードは、この国際標準でコンパイルできない場合があります。