3

この質問では、「pimpl: shared_ptr or unique_ptr」と尋ねました。pimpl イディオムの適切な使用法は、 aunique_ptrではなく aを使用することであると確信しましたshared_ptr。ユーザーにはポインターがまったくないかのように動作する必要がありますが、shared_ptrコピー時にエイリアシングが導入されることは明らかであり、これは間違いなくポインターのように動作します。

したがって、ユーザーがshared_ptr私の pimpl オブジェクトに を作成したいとしましょう (実際に複数のエイリアスが必要な場合など)。例えば:

shared_ptr<my_pimpl> p(new my_pimpl());

それは私の実装を指すことになりますshared_ptrunique_ptr

次のようなものを達成できればいいのですが:

my_pimpl x; // (1)
shared_ptr<my_pimpl> p(new my_pimpl()); // (2) Pointer to pointer here.
x.f(); // (3)
p->f(); // (4)

しかし、どうにかしてポインタからポインタへのポインタを取り除き、pimpl の実装の非表示を維持します。

これを達成する方法についてのアイデア (行 (2) と明らかに変更できてうれしいですが、my_pimpl行 (3) と (4) は同じままにしておきたい)。

4

2 に答える 2

2

制約に応じて、いくつかの可能なアプローチがあります。

1.独自のshared_my_pimplクラスを作成します

shared_my_pimplと同じインターフェースを持つmy_pimplが、内部的にはの代わりにshared_ptrを使用するクラスを作成しますunique_ptrshared_ptr_my_pimpl次に、を保持し、shared_my_pimploperator->のポインタを返すクラスを作成します。これにより、メンバーアクセスの表記ではなく表記shared_my_pimplを取得できます。関数を追加して、使用法のように見せることができます。->.make_shared_ptr_my_pimplshared_ptr

短所:

  1. オブジェクトのタイプは;ではありませshared_ptr<x>shared_ptr_my_pimpl。ふりをしているだけshared_ptrです。
  2. オブジェクトにmy_pimpl*またはを取得することはできません。my_pimpl&同じように動作する別のタイプです。

2.インターフェースから派生

関連するすべての機能を備えたインターフェースmy_pimpl_interfaceを純粋な仮想で作成します。my_pimplこのインターフェイスからとmy_pimpl::impl(pimpl実装クラス)の両方を取得します。make_shared_my_pimplをに返す関数を追加しshared_ptr<my_pimpl_interface>ますmy_pimpl::impl。これで、プレーンオブジェクトとshared_ptrオブジェクトの両方をとして参照できますmy_pimpl_interface&

短所:

  1. すべての関数を仮想化することにより、それらを呼び出す際に余分な間接参照が発生します。これは、回避しようとしていた可能性があります。標準my_pimplオブジェクトもこのオーバーヘッドを支払います。
于 2011-04-07T11:43:53.813 に答える
0

shared_ptrクラスのユーザーは、またはを使用するかどうかを選択できるため、この目的のためにインターフェイスを使用する必要がありますunique_ptr

于 2011-04-07T13:53:55.973 に答える