2012-04-23 11 views
5

shared_ptrのメンバ変数の初期化:shared_ptrメンバ変数を初期化する、新しいvs make_shared?

// .h 
class Customer 
{ 
public: 
    Customer(); 

private: 
    std::shared_ptr<OtherClass> something_; 
} 

// .cpp 
Customer(): 
    something_(new OtherClass()) 
{ 
} 

対は

Customer(): 
    something_(std::make_shared<OtherClass>()) 
{ 
} 

make_sharedバージョンが許可されていますか?私はいつも最初のバージョンを見ているようですが、それが好まれますか? make_sharedが許可されないある

+4

ハーブ・サッターはこれにGOTWを書きました。 [this](http://herbsutter.com/gotw/_103/)を参照し、[1つの問題](http://lanzkron.wordpress.com/2012/04/22/make_shared-almost-a-silver)もチェックしてください-bullet /)はハーブが明示的に述べていない。 –

+0

@RSamuelKlatchko - ansewerで使用した最初のリンクの更新リンクhttps://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ –

答えて

11

唯一の時間は、次のとおりです。

  1. あなたが他の誰かによって割り当てられた裸のポインタを取得し、shared_ptrでそれを保存している場合。これは、多くの場合、C APIとインタフェースする場合に当てはまります。
  2. 呼び出すコンストラクタがパブリックではない場合(make_sharedはパブリックコンストラクタのみを呼び出すことができます)。これは、ユーザーが工場からオブジェクトを作成するように強制するファクトリ関数で発生します。

    しかし、これを回避する方法があります。プライベートコンストラクタを持つ代わりに、パブリックコンストラクタを用意してください。しかし、コンストラクタを型にすることは、クラスへのプライベートアクセスを持つものによってのみ構築することができます。そうすれば、そのオブジェクトタイプのmake_sharedを呼び出すことができるのは、クラスへのプライベートアクセスを持つ人だけです。

はい、これを行うことができます。

+0

友情の問題については、友人として使用する特定の機能の標準に言及していますか?私はこの仕事をヘルパー関数に委ねるいくつかの実装をうまく想像することができました... –

+0

@MatthieuM:私はちょっと同じことを思っていたので、「可能かもしれない」と言いました。私はcomp.std.C++で尋ねました。彼らはそれについて何を言わなければならないのかを見るでしょう。もしそうでなければ、それはまともな欠陥報告のために作るかもしれないと思う。 –

3

この場合、make_sharedを使用することは許可されていませんが、それを使用する方が良いです。 newを使用すると、あなたの顧客のどこかにメモリを割り当て、shared_ptrのメモリを他の場所に割り当てて、弱い参照と弱い参照(弱いポインタと共有ポインタの両方)を格納します。 make_sharedを使用すると、メモリが1つしかなく、したがってすべてが新しいものが1つしかありません。

私は本当に明確であるとは確信していませんが、これはGotW #103の目的であり、そこによく説明されています。

関連する問題