C ++の空のstd :: shared_ptrとnullのstd :: shared_ptrの違いは何ですか?


80

cplusplus.comのshared_ptrページはの区別声をかけ、空 std::shared_ptrヌルを shared_ptrcppreference.comページには、明示的に両方の「空」との比較を区別を呼び出しますが、使用していないnullptrのその説明にstd::shared_ptr行動。

空とnullの間に違いはありますshared_ptrか?このような混合動作ポインタのユースケースはありますか?空でないnullshared_ptrは意味がありますか?通常の使用法(つまり、明示的に作成しなかった場合)で、空であるがnullではない結果になる可能性がある場合はありますshared_ptrか?

また、C ++ 11バージョンの代わりにBoostバージョンを使用している場合、これらの回答のいずれかが変わりますか?

回答:


80

それはshared_ptr行動の奇妙な一角です。何かshared_ptr所有、他の何かを指すを作成できるコンストラクターがあります。

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, T *ptr );

このshared_ptrコンストラクターを使用して構築されたものは、と所有権共有しますrが、ポイントするものをptr指します(つまり、を呼び出すget()か、またはoperator->()返しますptr)。これはptr、が所有するオブジェクトのサブオブジェクト(データメンバーなど)を指す場合に便利です。r

リンクしたページは、shared_ptr何もを所有していない、およびshared_ptr何も指していない(つまり、そのget() == nullptrnullを呼び出すaを呼び出します。(空は、標準によって、この意味で使用されているnullはあなたがnullではなく、空でないを構築することができません。)shared_ptrが、それは非常に有用ではないだろう。空であるがnullでshared_ptrはないものは本質的に所有権のないポインターであり、スタックに割り当てられたものへのポインターを、を期待する関数に渡すshared_ptrなどの奇妙なことを行うために使用できます(ただし、置く人は誰でもパンチすることをお勧めしますshared_ptrます最初にAPI)。

boost::shared_ptrこのコンストラクターありエイリアシングコンストラクターと呼ばます。


8
注目に値する:C ++11§20.7.2.2.1(p16)「注:このコンストラクターを使用するshared_ptrと、NULL以外の格納ポインターを使用して空のインスタンスを作成できます。」また、前述の注記(p15)に言及する価値があります。「ダングリングポインタの可能性を回避するために、このコンストラクタのユーザーはp、少なくともの所有権グループrが破棄されるまで、それが有効なままであることを確認する必要があります。」確かにめったに使用されない構造。
whozCraig 2014

@Cubbi Aはshared_ptr、何かを所有しているかどうかに関係なく、get()リターンnullptr 同等にnullptrなります。
TC

3
nullではなく、空でないshared_ptrsができ、すべての所有しているポインタがスコープ外に実行したら、必ずいくつかの機能が実行されます(でも、例外の場合には!)にするために、役立つこと。このための特別なクラスがあるかどうかはわかりません。
コールドフィックス2014

@coldfix null-but-nonemptyshared_ptrで、null-and- nonemptyではできないshared_ptrことは何ができますか?
TC

2
エイリアシングコンストラクターはBloombergに由来し、Boostに実装される前に標準として提案されました(N1851を参照)。私は、r「所有するものrは何でも所有する」という表現よりも、標準の「所有権を共有する」という用語を好みます
Jonathan Wakely 2015年

9

空のshared_ptrとnullのshared_ptrに違いはありますか?

空にshared_ptrは制御ブロックがなく、その使用カウントは0と見なされます。空のコピーshared_ptrは別の空shared_ptrです。それらは両方とも別個shared_ptrのものであり、共通の制御ブロックを持っていないため、それを共有しません。空shared_ptrは、デフォルトのコンストラクターまたはnullptr

空でないnullにshared_ptrは、他shared_ptrのsと共有できる制御ブロックがあります。空でないヌルのコピーがshared_ptrあるshared_ptrオリジナルと同じ制御ブロックその共有shared_ptrの使用回数は0ではないので、それはのすべてのコピーと言うことができるshared_ptrシェアは同じnullptr。空でないnullshared_ptrは、オブジェクトのタイプのnullポインタを使用して構築できます(nullptr

次に例を示します。

#include <iostream>
#include <memory>

int main()
{
    std::cout << "std::shared_ptr<int> ptr1:" << std::endl;
    {
        std::shared_ptr<int> ptr1;
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    std::cout << "std::shared_ptr<int> ptr1(nullptr):" << std::endl;
    {
        std::shared_ptr<int> ptr1(nullptr);
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    std::cout << "std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))" << std::endl;
    {
        std::shared_ptr<int> ptr1(static_cast<int*>(nullptr));
        std::cout << "\tuse count before copying ptr: " << ptr1.use_count() << std::endl;
        std::shared_ptr<int> ptr2 = ptr1;
        std::cout << "\tuse count  after copying ptr: " << ptr1.use_count() << std::endl;        
        std::cout << "\tptr1 is " << (ptr1 ? "not null" : "null") << std::endl;
    }
    std::cout << std::endl;

    return 0;
}

出力:

std::shared_ptr<int> ptr1:
    use count before copying ptr: 0
    use count  after copying ptr: 0
    ptr1 is null

std::shared_ptr<int> ptr1(nullptr):
    use count before copying ptr: 0
    use count  after copying ptr: 0
    ptr1 is null

std::shared_ptr<int> ptr1(static_cast<int*>(nullptr))
    use count before copying ptr: 1
    use count  after copying ptr: 2
    ptr1 is null

http://coliru.stacked-crooked.com/a/54f59730905ed2ff


1
これは、shared_ptrのカスタム削除プログラムでnullをチェックする必要がある理由のより良い答えだと思います。shared_ptrのカスタムdeleterでnullptrをチェックすることは意味がありますか?
デビッド・リー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.