0

vector に格納された auto_ptr を含む Classへのフォローアップとして、コピーの構築とコピーの代入の両方auto_ptrがユーザー定義である限り、コンテナー要素としてメンバーを持つクラスを使用しても問題ないという明言されていない結論があると思います(そうしないように) s コピー コンストラクターとコピー代入を呼び出します)。これについて、標準ライブラリの要件に違反するものはありますか?auto_ptr

慣用的にやり始めたいので、次の点に問題がある場合は教えてください。

#include <memory>
#include <algorithm>

class Y { /* ... */ };
class Z : public Y { /* ... */ };

class X {
    public:
        X() : ap(new Z()) {}
        X(const X& other) : ap(other.ap->clone()) {}
        X& operator=(X other) { swap(other); return *this; } // any problem with swap?
        void swap(X& other) { std::swap(ap, other.ap); }
        // note no destructor necessary
    private:
        std::auto_ptr<Y> ap; // Y provides clone()
};

私が気づいたことの 1 つは、このアプローチでは、Yのクラス定義が の定義のスコープ内にある必要があることですX(「生の」ポインタYが使用されている場合に前方宣言されるのとは対照的に)。これは、auto_ptrがインスタンス化されるときに、そのデストラクタが で delete を呼び出す必要があり、不完全な型であってはならないYためです。クラスが複数のリソースを管理する(複数のメンバーを持つ)Y場合、これは RAII の値と比較検討する必要があると思います。これについて何か考えはありますか?Xauto_ptr

この手法は全体的に優れていると思います。潜在的に複数のリソース (単一責任プリンシパル) を構築/破棄/コピーする必要があるクラスの多くのトリッキーなコードを排除するためです。auto_ptr目的を果たしているかどうか、または言語/標準ライブラリの微妙な要件のためにここで機能しないかどうか疑問に思っています。

私は他のタイプのスマート ポインターを認識していますが、ライブラリ インターフェイスを実装しているので、クライアントに Boost や TR1 の要件を課したくないことに注意してください。一般的なの使用に関する講義はすべてauto_ptr反対票を投じられます!

4

3 に答える 3

1

デストラクタがスコープ外のときにauto_ptrを使用すると、未定義の動作が発生します。MSVCはそれについて警告します。GCCはそうではありません。

デストラクタがインライン関数として定義されていない場合にのみ、機能させることができます。

unique_ptrとscoped_ptrは、この問題を修正します。少なくともそれらでは、誤って未定義のコードを書くことを防いでいます。

于 2010-11-23T20:00:34.147 に答える
1

の上に複製スマートポインターを実装したと思いますstd::auto_ptr。ダムポインターの上に実装することからそれほど遠くないので、これが面倒な価値があるかどうかはわかりません。

しかし、私が見る限り、これにはエラーはありません。(もちろん、私がこれを投稿してから5分後に誰かが明らかな欠陥を指摘するでしょう...)

于 2010-11-23T19:50:17.577 に答える
-1

あなたは本当に何をしようとしていますか?コンテナにたくさんのオブジェクトを入れたいだけなら、不必要な作業がたくさんあるようです。一時オブジェクトを作成し、コンテナ内のオブジェクトに所有権を引き継がせることは、私の考えでは問題ではありません

operator =()私には意味がありません、それはそうではありません=それはスワップです。

X a,b;
a=b
assert(a==b) // fail!

あなたの認識は正しくありません

私が気づいたことの1つは、このアプローチでは、Yのクラス定義がXの定義のスコープ内にある必要があることです(Yへの「生の」ポインターが使用される場合に前方宣言されるだけではありません)。これは、auto_ptrがインスタンス化されるときに、そのデストラクタがYに対してdeleteを呼び出す必要があるため、Yを不完全な型にすることはできないためです。

Xのデストラクタを定義し、CPPファイルに実装すると、合法的に実行できます。

ヘッダ

class Y;
class X{
  virtual ~X();
  std::auto_ptr<Y> ap; 
};

class Y{};
~X(){}
于 2010-11-23T20:00:39.080 に答える