2009-03-07 12 views
54

は以下と等価何ですか:boost :: shared_ptrを持つNULLポインタ?

std::vector<Foo*> vec; 
vec.push_back(NULL); 

boost::shared_ptrを扱いますか?それは次のコードですか?

std::vector< boost::shared_ptr<Foo> > vec; 
vec.push_back(boost::shared_ptr<Foo>()); 

注:このようなオブジェクトを多くプッシュバックすることがあります。私はグローバルな静的nullPtrオブジェクトをどこかに宣言すべきですか?そうすれば、それらのうちの1つだけを構築する必要があります:

boost::shared_ptr<Foo> nullPtr; 
+4

良いニュース:そこに、あなたが書くことができます "vec.emplace_backを();" NULLポインタを追加してください:) –

+7

オーバーヘッドが少なくて済む 'boost :: ptr_vector'の使用を検討してください。 – Philipp

答えて

0

はい、グローバルな静的ヌルポインタを宣言してください。

4

shared_ptr<Foo>のグローバルnullPtrを宣言できます。しかし、グローバルな名前空間を汚染すると、nullPtrshared_ptr<Bar>と呼びますか?

通常、NULL ptrをポインタのクラスの静的として宣言します。

#include <boost\shared_ptr.hpp> 

class Foo; // forward decl 
typedef boost::shared_ptr<Foo> FooPtr; 
class Foo 
{ 
public: 
    static FooPtr Null; 
} 
... 
// define static in cpp file 
FooPtr Foo::Null; 
... 
// use Foo Null 
vec.push_back(Foo::Null); 

こうして、各クラスにはスタティックNullがあります。

+1

テンプレート変数の変換演算子をグローバル変数で使用すると、より自然な構文を得ることができます。 ... :) –

52

あなたの提案(引数なしでshared_ptr<T>コンストラクタを呼び出す)は正しいです。 (値0のコンストラクタを呼び出すのは同等です。)vec.push_back()を既存のshared_ptr<T>で呼び出すよりも遅くなるとは思わないが、両方の場合(直接構築またはコピー構築のどちらでも)に構築が必要であるためです。

しかし、あなたが「よりよい」構文をしたい場合、あなたは以下のコードを試みることができる:

shared_ptr<int> pi(new int(42)); 
shared_ptr<SomeArbitraryType> psat(new SomeArbitraryType("foonly")); 

... 

pi = nullPtr; 
psat = nullPtr; 

注:

class { 
public: 
    template<typename T> 
    operator shared_ptr<T>() { return shared_ptr<T>(); } 
} nullPtr; 

をこれには、次の自然な構文を可能にし、単一のグローバルオブジェクトnullPtrを宣言これを複数の翻訳単位(ソースファイル)で使用する場合、クラスに名前(例:_shared_null_ptr_type)を与え、nullPtrオブジェクトの定義を別の.cppファイルに移動し、externの宣言をtに追加する必要があります彼はクラスが定義されているヘッダーファイルです。

+0

素敵なアイデアの男を私の答えを参照してください。 http://stackoverflow.com/questions/395685/how-do-you-choose-between-a-singleton-and-an-unnamed-class/395738# Pが、こっちの答えを注:私は+1それに持っていました395738 –

+0

ありがとうございました。 :) litbの投稿を見ると、クラスに実際に名前を付ける必要があることが示唆されています。 –

+0

いくつかの愚かな名前:nullPtrT、NullPtrType、nullPtr_t。何でも:)何かのインスタンスが1つしかない場合(nothrow_tとnullptr_tなど)、_tを追加していました。 –

17

まあ、これは合法である:

shared_ptr<Foo> foo; /* don't assign */ 

そして、この状態では、それが何を指していません。あなたも、このプロパティをテストすることができます。では、なぜこの

if (foo) { 
    // it points to something 
} else { 
    // no it doesn't 
} 

んではない:ここでは

std::vector < shared_ptr<Foo> > vec; 
vec.push_back (shared_ptr<Foo>); // push an unassigned one 
1

が、私は少し単純だと思う何かだとうまく

に動作しますが(typedefがあなたであることを覚えておいてください友人):

#include <cstdlib> 
#include <vector> 
#include <iostream> 
#include <boost/shared_ptr.hpp> 

typedef boost::shared_ptr< std::vector<char> > CharVecHandle; 

inline CharVecHandle newCharVec(std::vector<char>::size_type size) { 
    return CharVecHandle(new std::vector<char>(size)); 
} 

inline CharVecHandle newCharVec(void) { 
    return CharVecHandle(); 
} 

int main (void) 
{ 
    CharVecHandle cvh = newCharVec(); 

    if (cvh == NULL) 
     std::cout << "It's NULL" << std::endl; 
    else 
     std::cout << "It's not NULL" << std::endl; 

    std::vector<CharVecHandle> cvh_vec; 

    cvh_vec.push_back(newCharVec(64)); 
    cvh_vec.push_back(newCharVec()); 

    // or call the NULL constructor directly 
    cvh_vec.push_back(CharVecHandle()); 

    return EXIT_SUCCESS; 
} 
+0

には確かに存在していなかった実現、 'typedef'は' '後押しより:: shared_ptrのをを見て進歩して、 OPは単一の型 'Foo'のみに関係しているように見えます。この場合、' typedef'はうまく収まります。異なるタイプのスマートポインタ型の 'typedef'の拡散を避けたいのであれば、私のアプローチはより良いと思います。しかし、あなたの 'newCharVec()'関数でどのようなことを実証しようとしているのかは分かりませんが、説明できますか? –

+0

@j_random_hacker: 'newCharVec'関数の目的は、typedef、利便性、一貫性と同じです。実際のオブジェクトとNULLオブジェクトを作成する際に入力する文字数が少なく、一貫性があります。私がテンプレートメソッドを使用していたとしても、おそらくtypedefを作成することになります。あまりにも複雑な型宣言を見るときはいつも、 'C'のバックグラウンドから来て、私の最初の本能はtypedefです。それを考慮に入れて、実際にはある方法を選択する客観的な理由があるかどうか、スタイルや個人的な好みの問題かもしれません。 –

+0

私のアプローチを好む理由の1つは、私の 'nullPtr'はタイプに依存しないので、型が不明な変数を操作するときには関数テンプレート内で動作しますが、あなたはそうではありません。例えば。 Iは、関数テンプレートを作成することができ 'テンプレート push_a_null_ptr(ベクトル>&V){v.push_back(nullPtr)。 } '、すべての型' T'で動作します。私はそれが大きな逆さまではないことを認めますが、私には欠点はありません。 –

9

C++ 0xでは、単純にnullptrstd::shared_ptrへ:

std::vector< boost::shared_ptr<Foo> > vec; 
vec.push_back(nullptr); 
次のC++標準から
関連する問題