2017-01-18 16 views
15

shared_ptr<T>を作成するのにmake_shared<T>を使用すると、その制御ブロックにはTを格納するのに十分な大きさのストレージブロックが含まれていることが多くの場所で読み取られています。配置新しい。このような何か:なぜshared_ptrはプレースメントnewを使用するのですか

template<typename T> 
struct shared_ptr_control_block { 
    std::atomic<long> count; 
    std::atomic<long> weak_count; 
    std::aligned_storage_t<sizeof (T), alignof (T)> storage; 
}; 

しかし、我々はちょうどタイプの代わりにTとメンバ変数を持つことはできませんなぜ私は少し混乱していますか?なぜ生のストレージを作成して、新しいプレースメントを使用するのですか?通常のオブジェクトTと1つのステップで組み合わせることはできませんか?

答えて

18

これは、生涯管理を可能にするためです。

制御ブロックは、weak_countがゼロになるまで破棄されません。オブジェクトstorageは、countがゼロになるとすぐに破棄されます。これは、カウントがゼロになると、storageのデストラクタを直接呼び出す必要があることを意味し、は、コントロールブロックのデストラクタのではありません。

デストラクタを呼び出すコントロールブロックのデストラクタがstorageでないようにするには、storageの実際のタイプはTにできません。

強い参照カウントしかなかった場合、Tは問題なく(しかもはるかに簡単です)。


実際のところ、実装はこれより少し複雑です。 shared_ptrはTnewに割り当ててからshared_ptrを構築することで構築できます。

template<typename T> 
struct shared_ptr_control_block { 
    std::atomic<long> count; 
    std::atomic<long> weak_count; 
    T* ptr; 
}; 

と何make_shared割り当ては次のとおりです:したがって実際制御ブロックは、より多くのように見える

template<typename T> 
struct both { 
    shared_ptr_control_block cb; 
    std::aligned_storage_t<sizeof (T), alignof (T)> storage; 
}; 

そしてcb.pstorageのアドレスに設定されています。 both構造体をmake_sharedに割り当てると、2つではなく1つのメモリ割り当てが行われます(メモリ割り当ては高価です)。

注:shared_ptrデストラクタが制御ブロックがbothの一部であるかどうかを知る方法が必要です(この場合、完了するまでメモリを解放できません)以前は解放することができます)。これは、シンプルなブールフラグ(この場合、コントロールブロックがより大きい)、またはポインタ内のいくつかのスペアビット(ポータブルではありませんが、標準ライブラリ実装は移植可能である必要はありません)を使用することによって可能です。実装はさらに複雑なポインタにすべての場合はmake_sharedの場合に格納することを避けるために複雑にすることができます。

+0

ああ、わかりました。したがって、参照カウントが1つしかない場合(強いカウント)、 'T'で十分でしょうか? –

+0

@ZizhengTai、yes –

+0

必要なメモリ割り当ての数を減らすために、make_sharedがコントロールブロックとオブジェクトを組み合わせることに言及する価値があります。単純にshared_ptrを構築するには、共有されるオブジェクトに対して1つの割り当てが必要であり、制御ブロックに対して1つの割り当てが必要でした。 –

7

弱いポインタが格納されたオブジェクトよりも長く存続する可能性があるため、制御ブロックの有効期間は格納されたオブジェクトの有効期間を超えなければならないことがあります。管理対象オブジェクトがメンバ変数であれば、制御ブロックが破棄されたとき(またはデストラクタが2回呼び出されるとき)にのみ破棄される可能性があります。

オブジェクト自体が破棄された後でも記憶域が割り当てられたままになっているという事実は、メモリ制約システムでは実際にはmake_sharedというデメリットになります(実際に遭遇するかどうかはわかりませんが)。

関連する問題