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


217

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


5
多くの人がこれを誤解しているのを見たことがあるので、間違いなく+1です。質問するのは素晴らしい質問です。
Twokats 2008年

関連商品もお読みください。この質問はここで反対側から検討されます。auto_ptrおよびSTLコンテナーの詳細を理解するのに役立つ場合があります。 stackoverflow.com/questions/8630552/...
nickolay


1
moveセマンティックで、unique_ptrに関連する問題を回避するように設計されていauto_ptrます。C ++ 03では、auto_ptrコンパイラと言語がl値とr値を区別できなかったため、一部の「ハック」を使用して目的の動作を実現するため、言語はすべてのシナリオで正しく安全に動作するクラスを作成するのに十分強力ではありませんでした。ほとんどの時間。
Phil1970

ニースの記事:STLコンテナとAuto_ptrsは-なぜ彼らは混ぜないでくださいquantstart.com/articles/...を
alfC

回答:


124

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を持っていない場合は、スマートポインタやブースト同等物。 以下は、これらのスマートポインタに関するブーストライブラリのドキュメントです。


7
所有権を共有する必要がない場合は、ブーストポインターコンテナーも検討する必要があります。
me22 09/10/09

4
unique_ptrまた、コピーを許可しないため、特定のSTL操作は移動セマンティクスを使用できない限り正しく機能しません。
マイクウェラー2013

4
「この制限を克服するには、std::unique_ptrそのクラステンプレートを使用する必要があります」:移動セマンティクス(その仕様では右辺値参照が必要)のためにのみ存在できるため、基本的にはC ++ 11が必要です。ただし、(および関連して)C ++ 11標準では、STL要素の型は「コピー構築可能」かつ「割り当て可能」でなければならないとはもはや言われていません。移動構成可能で、移動割り当て可能で十分です。実際、unique_ptrインスタンスは移動構成可能であり、移動割り当て可能です。しかし、auto_ptrインスタンスもそうです!結果として、C ++ 11では、でauto_ptrできることを行うことができますunique_ptr
Marc van Leeuwen

@MarcvanLeeuwen(あなたresetrelease必要に応じて)
ラチェットフリーク

2
@ratchetfreak:うーん、わかりません。何?「あなたresetと」でなければrelease、コメントに何が当てはまるのかわかりません。auto_ptrとのunique_ptr両方にこれらのメソッドがあり、どちらの場合も同じことを行うことに注意してください。
マルクファンレーウェン2014

66

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

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

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


39

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


2年近くの間に、おそらく彼は目の前の問題に対処したと思います。
子犬

27
@DeadMG:はい、あなたは正しいです。しかし、それは私の目的ではありませんでした。誰かがこのスレッドにいつか来て、何かについて学びたいと思ってauto_ptrいるなら、これらのリンクは役に立つでしょう、私は確信しています。
Lazer

より最近の重複がたくさんあります。
パピー

8
@DeadMG:この質問は重複として閉じられなかったため、延長のために開かれています。レーザーはここでこれまで言われなかったことを言った。彼がたまたま来たと思います。
セバスチャンマッハ

を呼び出した後に問題を分析する2番目のリンクの説明は、sort()ここでのすべての回答よりも明確です。
カオシンク

17

STLコンテナーは、それらに格納されているアイテムをコピーできる必要があり、元のコピーとコピーが同等であることを想定して設計されています。自動ポインタオブジェクトは完全に異なるコントラクトを持ち、それによってコピーは所有権の譲渡を作成します。つまり、auto_ptrのコンテナは、使用方法によっては奇妙な動作を示します。

効果的なSTL(Scott Meyers)項目8に何が問題になるかについての詳細な説明と、効果的なC ++(Scott Meyers)項目13にはそれほど詳細ではない説明があります。


12

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


しかし、unique_ptrを使用する場合、オブジェクトの所有権を持つことができるunique_ptrは1つだけなので、ほとんど同じ結果になりますか?
トレーサー2014

2
@Tracer unique_ptrは、適切なC ++ 11オブジェクトと同様に、移動構築または割り当て時にのみリソースの所有権を転送できます。これにより、プログラマーはlvalueを渡さず、意図せずに/予期せずそれを変異させるのでstd::move(sourceObject)はなく、意図的または一時的に渡す必要があります。ここで徹底的に強調されているように、コピー割り当て...はの中心的な問題でした。auto_ptr
underscore_d

4

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コードは、この国際標準でコンパイルできない場合があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.