17

の使用に関するベスト プラクティスについていくつか質問がありshared_ptrます。

質問1

コピーはshared_ptr安いですか?それとも、自分のヘルパー関数への参照として渡し、値として返す必要がありますか? 何かのようなもの、

void init_fields(boost::shared_ptr<foo>& /*p_foo*/);
void init_other_fields(boost::shared_ptr<foo>& /*p_foo*/);

boost::shared_ptr<foo> create_foo()
{
    boost::shared_ptr<foo> p_foo(new foo);
    init_fields(p_foo);
    init_other_fields(p_foo);
}

質問2

boost::make_sharedを構築するために使用する必要がありshared_ptrますか? はいの場合、どのような利点がありますか? また、パラメーターのないコンストラクターがないmake_shared場合、どのように使用できますか?T

質問 3

使い方はconst foo*?これを行うための2つのアプローチを見つけました。

void take_const_foo(const foo* pfoo)
{

}

int main()
{
    boost::shared_ptr<foo> pfoo(new foo);
    take_const_foo(pfoo.get());
    return 0;
}

また

typedef boost::shared_ptr<foo> p_foo;
typedef const boost::shared_ptr<const foo> const_p_foo;

void take_const_foo(const_p_foo pfoo)
{

}

int main()
{
     boost::shared_ptr<foo> pfoo(new foo);
     take_const_foo(pfoo);
     return 0;
}

質問 4

オブジェクトに戻って確認するNULLにはどうすればよいですか? shared_ptrのようなものですか、

boost::shared_ptr<foo> get_foo()
{
     boost::shared_ptr<foo> null_foo;
     return null_foo;
}

int main()
{
     boost::shared_ptr<foo> f = get_foo();
     if(f == NULL)
     {
          /* .. */
     }
     return 0;
}

どんな助けでも素晴らしいでしょう。

4

5 に答える 5

8

ほとんどの質問には回答済みですが、shared_ptr のコピーが安価であることに同意しません。

コピーには、参照渡しとは異なるセマンティクスがあります。参照カウントが変更され、最良の場合はアトミックインクリメントがトリガーされ、最悪の場合はロックがトリガーされます。必要なセマンティクスを決定する必要があります。そうすれば、参照渡しか値渡しかがわかります。

パフォーマンスの観点からは、通常、shared_ptr のコンテナーではなくブースト ポインター コンテナーを使用することをお勧めします。

于 2010-01-27T10:45:12.950 に答える
4
  1. コピーは安価で、ポインターは多くのスペースを取りません。その要点は、コンテナーでの値による使用を可能にするために小さくすることでした (例: std::vector< shared_ptr<Foo> >)。

  2. make_shared可変量のパラメーターを取り、自分で構築するよりも好ましいメカニズムです ( のようにmake_pair)。利点は読みやすさです。特に、一時変数や名前空間の受け渡しが関係している場合:

  3. boost::const_ptr_castすでに提案されているように

  4. スマート ポインターにはオーバーロードされた演算子があり、bool に評価される式で直接使用できます。使用しないでくださいget。何でも。何かと比較する代わりにp.get、空のポインター インスタンスを比較します ( my_ptr != boost::shared_ptr< MyClass >())

AD.2

func_shared( boost::shared_ptr<my_tools::MyLongNamedClass>( 
    new my_tools::MyLongNamedClass( param1, param2 ) );

func_shared( boost::make_shared<my_tools::MyLongNamedClass>( param1, param2 ));
于 2010-01-27T09:13:48.953 に答える
3
  1. はい、コピーは絶対に安いです。ポインターを保持する以外に、(通常) shared_ptr クラスにはもう 1 つのデータ メンバー、つまり使用カウントがあります。
  2. これには答えられません。通常、make_shared が導入される前 (1.40?) のブースト バージョンを使用します。
  3. boost::const_pointer_cast を使用する
  4. shared_ptr には operator==/!= が定義されています。上記の例では: if (f)
于 2010-01-27T06:36:11.110 に答える
3
  1. shared_ptr をコピーすると、スタック コピーと追加の refcount のインクリメント/デクリメントで 32 バイトのコストがかかるようになりました。それがあなたにとって安いかどうかを判断してください。しかし、const 参照を渡さない理由はありません。特に、ptr の typedef が既にあるためです。 void f(const foo_ptr &myfoo) 特に、C++ で渡す標準の書き込み禁止パラメーターが const であることを考えると、参照。

  2. 共有されていないポインターを受け入れる関数がないことをお勧めします。これは、Java および C# のパラメーター受け渡しセマンティクスに似ています (同一ではありません)。1 つの標準的な方法ではなく、毎回オブジェクトを渡す方法を決定することに飛び込む必要はありません。

  3. if(p)通常のポインターと同じように使用します。ブール変換のセマンティクスは非常に優れています。

于 2010-01-27T10:57:24.030 に答える
2
  1. shared_ptr が存在する基本的な理由の 1 つは、比較的安価にコピーできることです。
  2. パラメータを取る make_shared のバージョンがあります (コンパイラが可変パラメータ リストをサポートする場合は可変パラメータ リストをサポートします)。
  3. const_ptr_cast を探しているようですね。
  4. null ポインタを返すには、share_ptr ctor に「0」を渡すことができます。null ポインターを確認するには、p.get() を 0 と比較します。
于 2010-01-27T06:02:16.397 に答える