1. ホーム
  2. c++

shared_ptr はテンプレート・パラメータを1つしか取らないのに、 unique_ptr はなぜ2つ取るのですか?

2023-09-27 20:36:45

質問

どちらも unique_ptr shared_ptr は、それらが所有するオブジェクト上で呼び出すカスタムデレッタを受け入れます。しかし unique_ptr のテンプレート・パラメータとして渡されます。 クラス の型であるのに対し shared_ptr のカスタムデイレクタのタイプは コンストラクタ .

template <class T, class D = default_delete<T>> 
class unique_ptr
{
    unique_ptr(T*, D&); //simplified
    ...
};

template<class T>
class shared_ptr
{
    template<typename D>
    shared_ptr(T*, D); //simplified
    ...
};

なぜこのような違いがあるのかわかりません。何がそれを必要とするのでしょうか?

どのように解決するのですか?

テンプレートの引数にdeleterを指定した場合(例えば unique_ptr のように)それは型の一部であり、この型のオブジェクトに何も追加で格納する必要はありません。 削除子がコンストラクタの引数として渡される場合(例えば shared_ptr のように) コンストラクタの引数として渡された場合は、それをオブジェクトに格納する必要があります。これは、同じ型のオブジェクトに異なるデレタを使用することができるため、柔軟性を高めるための代償でもあります。

これが理由なんでしょうね。 unique_ptr はオーバーヘッドがゼロの非常に軽量なオブジェクトであるはずです。デレタを格納するのは、それぞれの unique_ptr でデレタを格納すると、そのサイズが倍になる可能性があります。そのため、人々は古き良き生のポインターを代わりに使用するでしょうが、それは間違っています。

その一方で shared_ptr は参照カウントを保存する必要があるため、それほど軽量ではありません。したがって、カスタムデレタも保存することは良いトレードオフのように見えます。