通常のポインターと比較して、自動ポインター(auto_ptr)を使用することの長所と短所は何ですか?メモリの自動解放を行うと聞きましたが、なぜ頻繁に使用されないのですか?
9 に答える
の主な欠点はstd::auto_ptr、所有権の譲渡のセマンティクスがあることです。これによりstd::auto_ptr、要素を格納または取得するときにコンテナーがコピーコンストラクターを使用するため、STLコンテナーに格納できなくなります。
また、私が気付いたもう1つの重要な側面は、 PIMPLイディオムstd::auto_ptrの使用には役立たないということです。これは、ラップされたクラスのデストラクタの完全な定義が必要なためです。詳細については、clc++。mのこのスレッドを参照してください。
更新:所有権の譲渡
class Test {};
std::auto_ptr<Test> ap_test_1(new Test);
std::auto_ptr<Test> ap_test_2(new Test);
ap_test_2 = ap_test_1; // here ap_test_1's ownership is transferred i.e. ap_test_2 is the
// new owner and ap_test_1 is NULL.
STLアルゴリズムで使用されるSTLコンテナで使用した場合の意味の詳細については、HerbSutterのサイトにあるこのスレッドを参照してください。
スマートポインタはC++でよく使用されますが、おそらくそれほど頻繁ではありません。にはstd::auto_ptrいくつかの問題がありますが(たとえば、標準ライブラリコレクションでは使用できません)、他にも多くの問題があります。これらの中で最も人気のあるものは、Boostライブラリに付属しているものであり、次のC++標準の一部になる予定です。ご覧ください。
スマートポインタは主に所有権と動的に作成されたオブジェクトの削除に関するものであることに注意してください。動的に作成されたオブジェクトがない場合、通常はスマートポインターは必要ありません。
{
int i = 42;
auto_ptr <int> p( & i ); // bad!
}
オートポインターがスコープ外になると、iを削除しようとするため、これは実際には行いたくありません。残念ながら、私は動的に作成されなかったので、悪いことが起こります。したがって、ほとんどのC ++プログラムでは、スマートと通常の両方の種類のポインタが必要です。
auto_ptrの主な存在理由は、例外安全な方法で所有権を譲渡することです。ほとんどの人はそれを貧乏人のブーストとして使用しますが::scoped_ptr。
主な用途は、オブジェクトポインタをパラメータまたは戻り値として使用して戻る関数です。
たとえば、ファクトリ関数
std::auto_ptr<MyClass> createMyClass(MyClass::Type type) {
if (type == MyClass::TypeOne) {
return std::auto_ptr(new MyClassOne);
}
else {
return std::auto_ptr(new MyClassTwo);
}
}
void foo() {
std::auto_ptr<MyClass> myc = createMyClass(MyClass::TypeOne);
// use myc
}
このコードは非常に単純であり、例外がスローされても例外はスローされませんが、mycはそれを正しく処理しますが、rawポインターを使用してこれを行うのは困難です。
boost :: shared_ptrも使用できますが、これは必要以上の機能を提供し、オブジェクトが共有されることを期待していることも示します。auto_ptrを使用する方が簡単で、所有権を譲渡していることを明確に示しています。
最近、auto_ptrと同じ使用法で欠点がないように見えるboost::unique_ptrについて知らされました。
詳細については、スマートポインタを返す際のベストプラクティスを参照してください
自動ポインター(std :: auto_ptr)をスマートポインターのファミリー(特にstd :: auto_ptr、boost :: scoped_ptr、boost :: shared_ptr)と混同しないでください。
ほとんどの場合、参照を使用したいので、自動ポインターを使用することはほとんどありません。私が行うのは、オブジェクトのコンストラクターでインスタンス化できないメンバー変数の場合のみです。
それどころか、スマートポインターは非常に強力ですが、それはあなたの質問ではありません、私は推測します:)
利点は、単純な使用のために、彼らが彼らの仕事をするということです。
void foo() {
std::auto_ptr<int> bar(new int);
// do the stuff that potentially throw
} // the auto_ptr destructor will call delete here
欠点は、この単純な使用から逃れるとすぐに、auto_ptrの悪いセマンティクスにぶつかることです。
std::auto_ptr<int> foo(new int);
std::auto_ptr<int> bar = foo; // foo is changed here! It does not have ownership anymore.
優れたセマンティクスを持ち、boost ::で利用可能であり、次のC++標準のstd::で利用可能になるunique_ptrとshared_ptrを使用することをお勧めします。
おそらく、広く使用されていない最大の理由は次のとおりです。
std :: auto_ptrには、大きな欠点があります。破棄せずにコピーすることはできません。自動ポインタのコピーを作成する必要がある場合、元のインスタンスは破棄されます。これは、いつでもオブジェクトのコピーを1つだけ持つことができることを意味します。これは、auto_ptrを、vector、deque、list、set、mapなどの標準コンテナーでは使用できないことも意味します。実際、コピー構築に依存するクラスではほとんど使用できません。
さらに、auto_ptrは安全ではありません。これは、誤ってコピーを実行することを妨げるものが何もないためです。そうすると、元のコピーが破棄されます。また、一部の標準に準拠していないC ++コンパイラでは、前方宣言されたオブジェクトをauto_ptrに格納し、クラスの完全な定義を含めずにそれを使用できます。これにより、常にメモリリークが発生します。
auto_ptrには、それが指すオブジェクトの所有権モデルがあります。同じオブジェクトに対して複数の参照を持つことはできません。また、それらをstlコンテナなどに入れることもできません。実際に所有権を譲渡しているように見えるコードは、本番環境で厄介な追跡困難なバグを引き起こします。
boostのshared_ptrは、ほとんどすべての場合、はるかに実用的です。
短編小説:std :: auto_ptrは共有できませんが、通常のポインターは共有できます。
は複数の目的に使用auto_ptrできますが、ヒープ上のオブジェクトを割り当て、スコープのスタックフレームが終了したときにオブジェクトの割り当てを解除するためのツールが最適だと思います。
私見の唯一の本当の問題auto_ptrは名前です。人々はそれを見て、それがスマートポインターであると思いますが、もちろんそうではありません。
もし私たちがそれを何かのように呼んだら、私AutoDelete<T>たちはさまざまな種類の議論をするでしょう。:-)