Le cplusplus.com shared_ptr
page appelle une distinction entre un vide std::shared_ptr
et un null shared_ptr
. La page cppreference.com n'appelle pas explicitement la distinction, mais utilise à la fois "vide" et la comparaison avec nullptr
dans sa description de std::shared_ptr
comportement.
Y a-t-il une différence entre un vide et un nul shared_ptr
? Existe-t-il un cas d'utilisation pour de tels pointeurs à comportement mixte? Est-ce qu'un null non vide shared_ptr
même logique? Y aurait-il jamais un cas d'utilisation normale (c'est-à-dire si vous n'en avez pas explicitement construit un) où vous pourriez vous retrouver avec un _ vide mais non nul shared_ptr
?
Et l'une de ces réponses change-t-elle si vous utilisez la version Boost au lieu de la version C++ 11?
C'est un coin étrange du comportement de shared_ptr
. Il a un constructeur qui vous permet de créer un shared_ptr
Qui possède quelque chose et pointe vers autre chose:
template< class Y >
shared_ptr( const shared_ptr<Y>& r, T *ptr );
Le shared_ptr
Construit à l'aide de ce constructeur partage la propriété avec r
, mais points à tout ce que ptr
pointe vers (c'est-à-dire que l'appel de get()
ou operator->()
renverra ptr
). C'est pratique dans les cas où ptr
pointe vers un sous-objet (par exemple, un membre de données) de l'objet appartenant à r
.
La page que vous avez liée appelle un shared_ptr
Qui ne possède rien vide , et un shared_ptr
Qui ne pointe vers rien (c'est-à-dire, dont get() == nullptr
) null . ( Vide est utilisé dans ce sens par la norme; null isn ' t.) Vous pouvez construire un shared_ptr
nul mais non vide, mais ce ne sera pas très utile. Un shared_ptr
Vide mais non nul est essentiellement un pointeur non propriétaire, qui peut être utilisé pour faire des choses étranges comme passer un pointeur à quelque chose alloué sur la pile à une fonction attendant un shared_ptr
(mais je suggère de frapper celui qui a mis shared_ptr
Dans l'API en premier).
boost::shared_ptr
Aussi a ce constructeur , qu'ils appellent le constructeur d'alias .
Y a-t-il une différence entre un shared_ptr vide et un null shared_ptr?
shared_ptr
Vide n'a pas de bloc de contrôle et son compte d'utilisation est considéré comme 0. La copie de shared_ptr
Vide est un autre shared_ptr
Vide. Ce sont deux shared_ptr
Séparés qui ne partagent pas de bloc de contrôle commun car ils ne l'ont pas. shared_ptr
Vide peut être construit avec le constructeur par défaut ou avec un constructeur qui prend nullptr
.
Null non vide shared_ptr
A un bloc de contrôle qui peut être partagé avec d'autres shared_ptr
S. La copie du null non vide shared_ptr
Est shared_ptr
Qui partage le même bloc de contrôle que l'original shared_ptr
Donc le nombre d'utilisation n'est pas 0. Il on peut dire que toutes les copies de shared_ptr
partagent le même nullptr
. Un null non vide shared_ptr
Peut être construit avec un pointeur null de type objet (pas nullptr
)
Voici un exemple:
#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;
}
Il génère:
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