Comment : Créer et utiliser les instances de shared_ptr
Le type d' shared_ptr est un pointeur intelligent dans la bibliothèque C++ standard qui est conçu pour les scénarios dans lesquels plusieurs propriétaire peut devoir gérer la durée de vie de l'objet en mémoire.Après avoir initialisé shared_ptr que vous pouvez le copier, passez-le par valeur dans les arguments de fonction, et assignez-le à d'autres instances d' shared_ptr .Tout le point d'instances au même objet, et l'accès au partage à un « bloc de contrôle » qui incrémente et décrémente le décompte de références lorsque nouvel shared_ptr est ajouté, hors de portée, ou est réinitialisé.Lorsque le décompte de références atteint zéro, le bloc de contrôle supprime la ressource mémoire et elle-même.
L'illustration suivante représente plusieurs instances d' shared_ptr qui indiquent un emplacement de mémoire.
Exemple
Si possible, utilisez la fonction de make_shared (<memory>) pour créer shared_ptr lorsque la ressource mémoire est créée pour la première fois.make_shared est sécurisée du point.Il utilise le même appel pour allouer de la mémoire pour le bloc de contrôle et la ressource, et réduit ainsi la charge mémoire de construction.Si vous n'utilisez pas make_shared, vous devez utiliser une nouvelle expression explicite pour créer l'objet avant de les passer au constructeur d' shared_ptr .L'exemple suivant illustre plusieurs méthodes permettant de déclarer et initialiser shared_ptr avec un objet.
// Use make_shared function when possible.
auto sp1 = make_shared<Song>(L"The Beatles", L"Im Happy Just to Dance With You");
// Ok, but slightly less efficient.
// Note: Using new expression as constructor argument
// creates no named variable for other code to access.
shared_ptr<Song> sp2(new Song(L"Lady Gaga", L"Just Dance"));
// When initialization must be separate from declaration, e.g. class members,
// initialize with nullptr to make your programming intent explicit.
shared_ptr<Song> sp5(nullptr);
//Equivalent to: shared_ptr<Song> sp5;
//...
sp5 = make_shared<Song>(L"Elton John", L"I'm Still Standing");
L'exemple suivant montre comment déclarer et initialiser les instances d' shared_ptr qui prennent la propriété partagée d'un objet qui a déjà été alloué par un autre shared_ptr.Supposons qu' sp2 est shared_ptrinitialisé.
//Initialize with copy constructor. Increments ref count.
auto sp3(sp2);
//Initialize via assignment. Increments ref count.
auto sp4 = sp2;
//Initialize with nullptr. sp7 is empty.
shared_ptr<Song> sp7(nullptr);
// Initialize with another shared_ptr. sp1 and sp2
// swap pointers as well as ref counts.
sp1.swap(sp2);
shared_ptr est également utile dans les conteneurs de (STL) de modèles Standard lorsque vous utilisez des algorithmes qui copiez les éléments.Vous pouvez encapsuler des éléments dans shared_ptr, puis le copier dans d'autres conteneurs à condition que la mémoire sous-jacente soit valide tant que vous avez besoin, et plus encore.L'exemple suivant indique comment utiliser l'algorithme pour replace_copy_if sur les instances d' shared_ptr dans un vecteur.
vector<shared_ptr<Song>> v;
v.push_back(make_shared<Song>(L"Bob Dylan", L"The Times They Are A Changing"));
v.push_back(make_shared<Song>(L"Aretha Franklin", L"Bridge Over Troubled Water"));
v.push_back(make_shared<Song>(L"Thal�a", L"Entre El Mar y Una Estrella"));
vector<shared_ptr<Song>> v2;
remove_copy_if(v.begin(), v.end(), back_inserter(v2), [] (shared_ptr<Song> s)
{
return s->artist.compare(L"Bob Dylan") == 0;
});
for_each(v2.begin(), v2.end(), [] (shared_ptr<Song> s)
{
wcout << s->artist << L":" << s->title << endl;
});
Vous pouvez utiliser dynamic_pointer_cast, static_pointer_cast, et const_pointer_cast pour effectuer un cast shared_ptr.Ces fonctions sont similaires à dynamic_cast, à static_cast, et aux opérateurs d' const_cast .L'exemple suivant montre comment tester le type dérivé de chaque élément dans un vecteur d' shared_ptr des classes de base, puis copie les éléments et affiche des informations sur eux.
vector<shared_ptr<MediaAsset>> assets;
assets.push_back(shared_ptr<Song>(new Song(L"Himesh Reshammiya", L"Tera Surroor")));
assets.push_back(shared_ptr<Song>(new Song(L"Penaz Masani", L"Tu Dil De De")));
assets.push_back(shared_ptr<Photo>(new Photo(L"2011-04-06", L"Redmond, WA", L"Soccer field at Microsoft.")));
vector<shared_ptr<MediaAsset>> photos;
copy_if(assets.begin(), assets.end(), back_inserter(photos), [] (shared_ptr<MediaAsset> p) -> bool
{
// Use dynamic_pointer_cast to test whether
// element is a shared_ptr<Photo>.
shared_ptr<Photo> temp = dynamic_pointer_cast<Photo>(p);
return temp.get() != nullptr;
});
for_each(photos.begin(), photos.end(), [] (shared_ptr<MediaAsset> p)
{
// We know that the photos vector contains only
// shared_ptr<Photo> objects, so use static_cast.
wcout << "Photo location: " << (static_pointer_cast<Photo>(p))->location_ << endl;
});
Vous pouvez passer shared_ptr à une autre fonction des façons suivantes :
Passez shared_ptr par valeur.Il appelle le constructeur de copie, incrémente le décompte de références, et fait à l'appelé un propriétaire.Il existe une petite quantité de charge mémoire dans cette opération, qui peut être considérablement selon le nombre d'objets d' shared_ptr vous passez.Utilisez cette option lorsque le contrat de code (implicite ou explicite) entre l'appelant et l'appelé requiert que l'appelé soit un propriétaire.
Passez shared_ptr par référence ou référence const.Dans ce cas, le décompte de références n'est pas incrémenté, et l'appelé peut accéder au pointeur tant que l'appelant n'affiche pas de portée.Ou, l'appelé peut décider de créer shared_ptr sur la référence, et de devenir ainsi à un propriétaire partagé.Utilisez cette option lorsque l'appelant n'a aucune connaissance de l'appelé, ou lorsque vous devez passer shared_ptr et souhaiter éviter l'opération de copie pour des raisons de performance.
Passez le pointeur sous-jacent ou une référence à l'objet sous-jacent.Cela permet à l'appelé d'utiliser l'objet, mais ne lui permet pas de partager la propriété ou d'étendre la durée de vie.Si l'appelé crée shared_ptr du pointeur brut, nouvel shared_ptr est indépendant de l'origine, et ne vérifie pas la ressource sous-jacente.Utilisez cette option lorsque le contrat entre l'appelant et l'appelé indique clairement que l'appelant conserve la propriété de la durée de vie d' shared_ptr .
Lorsque vous décidez comment passer shared_ptr, déterminez si l'appelé doit partager la propriété de la ressource sous-jacente.Un « propriétaire est un objet ou fonctionne pour lequel peut contenir la ressource sous-jacente active tant que elle a besoin.Si l'appelant doit garantir que l'appelé peut prolonger la vie du pointeur au delà de sa (durée de vie de la fonction), utilisez le premier choix.Si vous ne vous inquiétez pas si l'appelé étend la durée de vie, le passage par référence et let l'appelé la copier ou pas.
Si vous devez fournir un accès de fonction d'assistance au pointeur sous-jacent, et vous savez que la fonction d'assistance utilise simplement le pointeur et retourne avant l'appel de la fonction, alors que la fonction ne doit pas partager la propriété du pointeur sous-jacent.Elle doit simplement accéder au pointeur dans la durée de vie d' shared_ptrde l'appelant.Dans ce cas, il est possible de passer shared_ptr par référence, ou passez le pointeur brut ou une référence à l'objet sous-jacent.Passer cette méthode fournit un petit avantage en matière de performances, et peut également vous aider à exprimer votre intention de programmation.
Parfois, par exemple dans std:vector<shared_ptr<T>>, vous devrez peut-être passer chaque shared_ptr dans un corps d'expression lambda ou un objet nommé de fonction.Si le lambda ou fonction ne stocke pas le pointeur, puis passez shared_ptr par référence au au comment appeler le constructeur de copie pour chaque élément.
L'exemple suivant montre comment shared_ptr surcharge plusieurs opérateurs de comparaison pour activer les comparaisons de pointeur dans la mémoire qui est possédée par les instances d' shared_ptr .
// Initialize two separate raw pointers.
// Note that they contain the same values.
auto song1 = new Song(L"Village People", L"YMCA");
auto song2 = new Song(L"Village People", L"YMCA");
// Create two unrelated shared_ptrs.
shared_ptr<Song> p1(song1);
shared_ptr<Song> p2(song2);
// Unrelated shared_ptrs are never equal.
wcout << "p1 < p2 = " << std::boolalpha << (p1 < p2) << endl;
wcout << "p1 == p2 = " << std::boolalpha <<(p1 == p2) << endl;
// Related shared_ptr instances are always equal.
shared_ptr<Song> p3(p2);
wcout << "p3 == p2 = " << std::boolalpha << (p3 == p2) << endl;