9

ScottMeyersのEffectiveC++の項目18で、インターフェイスを正しく使いやすく、正しく使いにくいようにする、と彼はnullshared_ptrについて言及しました。

std::tr1::shared_ptr<Investment> pInv(static_cast<Investment*>(0), getRidOfInvestment)

と流行の割り当て操作

pInv = ...     //make retVal point to the correct object

その場合、nullのshared_ptrを作成し、後で割り当てを行う必要がありますか?リソース(生のポインター)があるときはいつでも、shared_ptrを作成しないのはなぜですか?

前の例ではScottMeyersが完全な代入を示していなかったため、shared_ptrの代入演算子がオーバーロードされてこれを実行できると思いました。

pInv = new Investment;    // pInv will take charge of the pointer
                          // but meanwhile keep the delete function it already had

しかし、私はブーストの実装で試しましたが、このようには機能しません。では、nullのshared_ptrを使用する意味は何ですか?

私はここで何かが欠けているとほぼ確信しています。誰かが私を助けてください。

ps。shared_ptrの初期化と割り当てについての詳細

#include <boost/shared_ptr.hpp>

int main(int argc, char *argv[])
{
    boost::shared_ptr<int> ptr1(new int);
    boost::shared_ptr<int> ptr2;
    ptr2.reset(new int);
    boost::shared_ptr<int> ptr3 = new int;

    return 0;
}

この例は、 g ++(Ubuntu / Linaro 4.5.2-8ubuntu4)4.5.2および最新のブーストではコンパイルできません。

sptr.cpp: In function ‘int main(int, char**)’:
sptr.cpp:8:39: error: conversion from ‘int*’ to non-scalar type ‘boost::shared_ptr<int>’    requested
4

3 に答える 3

22

null (空) を取得するためにそのハックを使用する必要はありませんshared_ptr。デフォルトのコンストラクターを使用するだけです。

std::shared_ptr<Investment> pInv; // starts null

へのポインターを割り当てるにはshared_ptr、構築時に次のいずれかを行います。

std::shared_ptr<Investment> pInt(new Investment);
// not allowed due to explicit annotation on constructor:
// std::shared_ptr<Investment> pInt = new Investment;

または、次の.reset()関数を使用します。

pInt.reset(new Investment);

その記事の著者がカスタムのデリータ ( getRidOfInvestment) を提供するつもりだった可能性があります。ただし、デリータ関数は、.reset()呼び出されたとき、または内部ポインタが変更されたときにリセットされます。カスタムのデリータが必要な場合は.reset()、 の作成時に に渡す必要がありますshared_ptr

これをより確実にするために使用したいパターンの 1 つは、カスタム作成関数です。

class Investment {
protected:
  Investment();
  // ...
public:
  static shared_ptr<Investment> create();
};

shared_ptr<Investment> Investment::create() {
  return shared_ptr<Investment>(new Investment, getRidOfInvestment);
}

後で:

shared_ptr<Investment> pInv = Investment::create();

shared_ptrこれにより、から作成された に常に正しいデストラクタ関数がアタッチされInvestmentます。

于 2011-07-28T21:48:37.563 に答える
7

null の raw ポインターを持つのと同じ理由です。

あなたが持っていると言う:

typedef std::tr1::shared_ptr<Investment> InvestmentPtr;
map<key,InvestmentPtr> portfolio;
...
get(mykey) {
  iterator it = portfolio.find(mykey);
  if (it == portfolio.end()) 
    return InvestmentPtr();
  else 
    return it->second;
  }
}

これにより、次のことが可能になります。

InvestmentPtr p = get(key);
if (p) ...
于 2011-07-28T21:53:07.603 に答える
2

オブジェクトをデフォルトで構築可能にしたい理由はたくさんあります。何よりもまず、スマート ポインターを生のポインターにできる限り類似させたいと考えています。また、int * p;(そして未定義の初期化されていないポインターを取得する) ことができるshared_ptr<int> p;ので、どこも指していないポインターを言って取得することもできます。 (ただし、 でテストできます!)。

最も説得力のある理由の 1 つは、おそらくshared_ptrs を使用してコンテナーを作成できることであり、その場で指先を割り当てなくてもコンテナーを満たすことができます。

于 2011-07-28T21:49:05.777 に答える