4

関連するいくつかのオブジェクト タイプへの参照を公開するライブラリを作成しました。これらのオブジェクトはすべて、ライブラリによって内部的に管理されているライフタイムを持っています。boost::shared_ptr

ライブラリのユーザーは、ライブラリの性質上、公開されたオブジェクトの有効期間を知ることもできます。そのため、これらのオブジェクトへのポインターを格納したり、参照を保持したりできます。彼らがこれを行い、それらのオブジェクトがいつ有効でなくなるかを知ることは合理的です。

しかし、ユーザーに合理的なことを強制することに罪悪感を覚えます。

weak_ptrライブラリが をそのオブジェクトに公開することは許容されますか? 他のライブラリはこれを行っていますか?

アプリでのこのライブラリの使用法をプロファイリングしたところ、weak_ptr排他的に公開するにはあまりにもミッション クリティカルであることがわかりました。

一致する API 関数で参照またはweak_ptr を公開するか、任意のオブジェクトweak_ptrをそれ自体に公開できるようにする方が賢明でしょうか?

4

5 に答える 5

6

smart_ptrライブラリのユーザーが s に直接アクセスできる場合、対応するs コンストラクターweak_ptrを介して s にアクセスできます。weak_ptrしかし、smart_ptrがすべてライブラリの内部にある場合、それは別の話です。

weak_ptrその場合、ライブラリが提供する他のアクセスに加えて、各オブジェクトがそれ自体に s を渡すようにすることをお勧めします。これにより、ユーザーは最大限の柔軟性を得ることができます。必要な場合はweak_ptr、すぐにアクセスできます。が必要な場合はshared_ptr、簡単に入手できます。オブジェクト自体へのアクセスのみが必要な場合は、スマート ポインターを完全に無視できます。

もちろん、あなたのライブラリが何をするのか、どのように使用または設計されているのかはわかりません。それは私の推薦を変えるかもしれません。

于 2009-03-15T02:05:55.223 に答える
4

ライブラリのオブジェクトを取得するための複雑なメカニズムを考え出すと、人々がライブラリを使用しなくなるだけです。ライブラリのセマンティクスにより、weak_ptrs を使用する必要がある場合、オブジェクトがある時点でなくなる可能性があることをユーザーが知っていることを回避する方法はありません。ライブラリの使用法に関するできるだけ多くの情報をインターフェイスで表現し、ドキュメントを控えて、使いやすさを無限に高めます。

悪い/経験の浅いユーザーを中心に設計することはできません。

于 2009-03-18T17:35:36.847 に答える
2

クライアントに s へのアクセスを許可すると、クライアントweak_ptrはそれらをロックしてshared_ptrs を作成し、最終的にオブジェクトの破棄を遅らせることができます。これにより、ライブラリに問題が発生する可能性があります。

weak_ptraを他のクラスでラップし、呼び出し元に ashared_ptrを渡すことをお勧めします。そうすれば、彼らはただ呼び出すことはできませんweak_ptr<T>::lock()。実装方法に影響を与える可能性のあるパフォーマンスの制約があるようですが、ライブラリの内部にshared_ptr<InterfaceClass>クラスを保持するのが良い方法かもしれません。weak_ptr

そうすれば、これらの実装の詳細をライブラリ インターフェイスから除外し、インターフェイスを変更せずに実装方法を変更することもできます。

于 2009-03-17T04:59:21.920 に答える
1

特にTR1に同様のスマートポインター(PDF)があることを考えると、weak_ptrsの公開に問題はありません。

TR1は主にVisualStudioとGCCによって実装されていますが、他のコンパイラの一部は実装されていません。ただし、関心のあるすべてのコンパイラに実装されている場合は、代わりにAPIを作り直してそれらのスマートポインタを公開することをお勧めします。

于 2009-03-10T17:27:40.340 に答える
0

ライブラリの無効な使用 (オブジェクトが削除されたときにオブジェクトにアクセスしようとする) をトラップし、高パフォーマンスの API (API に weak_ptr と shared_ptr がない) の両方が必要な場合は、別の API を使用することを検討できます。デバッグおよび非デバッグ ビルド用。

簡単にするために、公開するオブジェクトのクラスが 1 つしかないと仮定しましょう。このクラスを Object と呼びます。内部オブジェクトにアクセスするために API から返すポインター型は、次のように定義されます。

#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr 
#else
typedef Object * ObjectPtr;
#endif

ここでファサードはあなたが書くクラスです。おおよそ次のように機能します。

class ObjectPtrFacade {
public:
    ObjectPtrFacade(Object *o) : wptr(o) { }
    // copy constructor and assignment here etc. (not written)
    Object * operator -> () const { return access(); }
    Object & operator * () const { return *access(); }
private:
    Object * access() { 
      assert(wptr.use_count() > 0);
      return (Object *)(wptr.lock());
    }
    weak_ptr<Object> wptr; 
}

このように、デバッグ ビルドをビルドするときはいつでも、オブジェクトにアクセスする前に use_count() が 0 より大きいこと、つまりオブジェクトがまだ存在することをアサートする特別な種類のスマート ポインターが使用されます。オブジェクトが解放されている場合は、失敗したアサートが発生します。これは、null ポインター参照よりも優れています。

もちろん、一般に、API の「愚かな」ユーザーがいる場合、weak_ptr を使用しても役に立たないのは、そのユーザーが lock() を呼び出して、weak_ptr が空の shared_ptr を返した後にヌル ポインター参照を作成できるためです。 ..

于 2009-03-21T01:57:43.913 に答える