What is the difference between empty and null std :: shared_ptr in C ++?

The cplusplus.com shared_ptr page causes a distinction between an empty std::shared_ptr and a zero shared_ptr . The cppreference.com page does not explicitly indicate a difference, but the description of the behavior of std::shared_ptr uses both "empty" and comparison with nullptr .

Is there a difference between empty and null shared_ptr ? Is there any precedent for such pointers with mixed behavior? Does the null shared_ptr number make sense? Would there ever be a case with normal use (i.e., if you did not explicitly build it), where could you get an empty but not null shared_ptr ?

And if any of these answers change, if you use the Boost version instead of the C ++ 11 version?

+67
c ++ c ++ 11 shared-ptr
Sep 18 '14 at 19:16
source share
2 answers

This is a strange angle to the behavior of shared_ptr . It has a constructor that allows you to do shared_ptr , which owns something, and points to something else:

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

shared_ptr built using this constructor has ownership of r , but indicates what ptr points to (i.e., calling get() or operator->() will return ptr ). This is convenient for cases when ptr points to a subobject (for example, a data element) of an object belonging to r .

On the page with which you are linking calls, shared_ptr , which has nothing empty, and shared_ptr , which indicates nothing (i.e. whose get() == nullptr ) is null. (Empty is used in this sense by standard, null is not.) You can build empty, but not empty shared_ptr , but it will not be very useful. An empty but not null shared_ptr is essentially a non-owning pointer that can be used to do some strange things, such as passing a pointer to something allocated on the stack, to a function that expects shared_ptr (but I would suggest punching the one who first puts shared_ptr in the API).

boost::shared_ptr also has this constructor , which they call the alias constructor.

+70
Sep 18 '14 at 19:23
source share

Is there any difference between empty and null shared_ptr?

Empty shared_ptr does not have a control block, and its usage account is considered equal to 0. A copy of the empty shared_ptr is another empty shared_ptr . They are both separate shared_ptr , which do not have a common control unit, because it does not have one. An empty shared_ptr can be built using the default constructor or with a constructor that accepts nullptr .

A non-empty null shared_ptr has a control unit that can be used in conjunction with other shared_ptr s. The copy of the non-empty null shared_ptr is shared_ptr , which has the same control unit as the original shared_ptr , so the use of count is not 0. It can be said that all copies of shared_ptr have the same nullptr . A non-empty null shared_ptr can be created with a null object type pointer (not nullptr )

Here is an example:

 #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; } 

It outputs:

 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

+2
May 16 '16 at 12:04
source share



All Articles