Classe shared_ptr
Encapsule un pointeur intelligent contenant des références autour d'un objet alloué dynamiquement.
Syntaxe
template <class T>
class shared_ptr;
Notes
La shared_ptr
classe décrit un objet qui utilise le comptage de références pour gérer les ressources. Un objet shared_ptr
contient en fait un pointeur vers la ressource qu'il possède ou contient un pointeur null. Une ressource peut être détenue par plusieurs objets shared_ptr
. Quand le dernier objet shared_ptr
qui possède une ressource particulière est détruit, la ressource est libérée.
Un shared_ptr
arrêt de la propriété d’une ressource lorsqu’elle est réaffectée ou réinitialisée.
L'argument de modèle T
peut être un type incomplet, sauf comme mentionné pour certaines fonctions membres.
Quand un objet shared_ptr<T>
est construit à partir d'un pointeur de ressource de type G*
ou à partir d'un shared_ptr<G>
, le type de pointeur G*
doit être convertible en T*
. S’il n’est pas convertible, le code ne sera pas compilé. Par exemple :
#include <memory>
using namespace std;
class F {};
class G : public F {};
shared_ptr<G> sp0(new G); // okay, template parameter G and argument G*
shared_ptr<G> sp1(sp0); // okay, template parameter G and argument shared_ptr<G>
shared_ptr<F> sp2(new G); // okay, G* convertible to F*
shared_ptr<F> sp3(sp0); // okay, template parameter F and argument shared_ptr<G>
shared_ptr<F> sp4(sp2); // okay, template parameter F and argument shared_ptr<F>
shared_ptr<int> sp5(new G); // error, G* not convertible to int*
shared_ptr<int> sp6(sp2); // error, template parameter int and argument shared_ptr<F>
Un objet shared_ptr
possède une ressource :
s'il a été construit avec un pointeur vers cette ressource ;
s'il a été construit à partir d'un objet
shared_ptr
qui possède cette ressource ;s’il a été construit à partir d’un
weak_ptr
objet qui pointe vers cette ressource, ousi la propriété de cette ressource a été affectée, avec
shared_ptr::operator=
ou en appelant la fonctionshared_ptr::reset
membre.
Les objets shared_ptr
qui sont propriétaires d'une ressource partagent un bloc de contrôle. Le bloc de contrôle contient :
le nombre d'objets
shared_ptr
qui sont propriétaires de la ressource ;le nombre d'objets
weak_ptr
qui pointent vers la ressource ;le suppresseur de cette ressource, le cas échéant ;
l'allocateur personnalisé pour le bloc de contrôle, le cas échéant.
Un shared_ptr
objet initialisé à l’aide d’un pointeur Null a un bloc de contrôle et n’est pas vide. Une fois qu'un objet shared_ptr
a libéré une ressource, il n'en est plus propriétaire. Une fois qu'un objet weak_ptr
a libéré une ressource, il ne pointe plus vers cette ressource.
Quand le nombre d'objets shared_ptr
propriétaires d'une ressource devient égal à zéro, la ressource est libérée, soit en étant supprimée, soit en passant son adresse à un suppresseur, selon la façon dont la propriété de la ressource a été créée initialement. Quand le nombre d'objets shared_ptr
propriétaires d'une ressource est égal à zéro et que le nombre d'objets weak_ptr
qui pointent vers cette ressource est égal à zéro, le bloc de contrôle est libéré, à l'aide de l'allocateur personnalisé du bloc de contrôle s'il en a un.
Un objet vide shared_ptr
ne possède aucune ressource et n’a aucun bloc de contrôle.
Un suppresseur est un objet de fonction qui a une fonction membre operator()
. Son type doit être constructible par copie et son constructeur de copie et son destructeur ne doivent pas lever d'exceptions. Il accepte un paramètre, l'objet à supprimer.
Certaines fonctions acceptent une liste d'arguments qui définit les propriétés de l'objet shared_ptr<T>
ou weak_ptr<T>
résultant. Vous pouvez spécifier une telle liste d'arguments de plusieurs façons :
aucun argument : l’objet résultant est un objet vide shared_ptr
ou un objet vide weak_ptr
.
ptr
: pointeur de type Other*
vers la ressource à gérer. T
doit être un type complet. Si la fonction échoue (car le bloc de contrôle ne peut pas être alloué), elle évalue l’expression delete ptr
.
ptr, deleter
: pointeur de type Other*
vers la ressource à gérer et supprimer pour cette ressource. Si la fonction échoue (car le bloc de contrôle ne peut pas être alloué), il appelle deleter(ptr)
, qui doit être bien défini.
ptr, deleter, alloc
: pointeur de type Other*
vers la ressource à gérer, un deleter pour cette ressource et un allocateur pour gérer tout stockage qui doit être alloué et libéré. Si la fonction échoue (car le bloc de contrôle ne peut pas être alloué), il appelle deleter(ptr)
, qui doit être bien défini.
sp
: objet shared_ptr<Other>
qui possède la ressource à gérer.
wp
: objet weak_ptr<Other>
qui pointe vers la ressource à gérer.
ap
: objet auto_ptr<Other>
qui contient un pointeur vers la ressource à gérer. Si la fonction réussit, elle appelle ap.release()
; sinon elle reste ap
inchangée.
Dans tous les cas, le type de pointeur Other*
doit être convertible en T*
.
Cohérence de thread
Plusieurs threads peuvent lire et écrire différents objets shared_ptr
simultanément, même quand les objets sont des copies qui partagent la propriété.
Membres
Nom | Description |
---|---|
Constructeurs | |
shared_ptr |
Construit un objet shared_ptr . |
~shared_ptr |
Détruit un shared_ptr . |
Typedefs | |
element_type |
Type d’un élément. |
weak_type |
Type d’un pointeur faible vers un élément. |
Fonctions membres | |
get |
Obtient l'adresse de la ressource détenue. |
owner_before |
Retourne true si ce shared_ptr est classé avant le pointeur fourni (ou est inférieur à celui-ci). |
reset |
Remplacer la ressource détenue. |
swap |
Échange deux objets shared_ptr . |
unique |
Teste si la ressource détenue est unique. |
use_count |
Compte le nombre de propriétaires de ressources. |
Opérateurs | |
operator bool |
Teste si une ressource détenue existe. |
operator* |
Obtient la valeur désignée. |
operator= |
Remplace la ressource détenue. |
operator-> |
Obtient un pointeur vers la valeur désignée. |
element_type
Type d’un élément.
typedef T element_type; // before C++17
using element_type = remove_extent_t<T>; // C++17
Notes
Le element_type
type est un synonyme du paramètre T
de modèle.
Exemple
// std__memory__shared_ptr_element_type.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp0(new int(5));
std::shared_ptr<int>::element_type val = *sp0;
std::cout << "*sp0 == " << val << std::endl;
return (0);
}
*sp0 == 5
get
Obtient l'adresse de la ressource détenue.
element_type* get() const noexcept;
Notes
La fonction membre retourne l’adresse de la ressource détenue. Si l’objet ne possède pas de ressource, il retourne 0.
Exemple
// std__memory__shared_ptr_get.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp0;
std::shared_ptr<int> sp1(new int(5));
std::cout << "sp0.get() == 0 == " << std::boolalpha
<< (sp0.get() == 0) << std::endl;
std::cout << "*sp1.get() == " << *sp1.get() << std::endl;
return (0);
}
sp0.get() == 0 == true
*sp1.get() == 5
operator bool
Teste si une ressource détenue existe.
explicit operator bool() const noexcept;
Notes
L’opérateur retourne une valeur de true
quand get() != nullptr
, sinon false
.
Exemple
// std__memory__shared_ptr_operator_bool.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp0;
std::shared_ptr<int> sp1(new int(5));
std::cout << "(bool)sp0 == " << std::boolalpha
<< (bool)sp0 << std::endl;
std::cout << "(bool)sp1 == " << std::boolalpha
<< (bool)sp1 << std::endl;
return (0);
}
(bool)sp0 == false
(bool)sp1 == true
operator*
Obtient la valeur désignée.
T& operator*() const noexcept;
Notes
L’opérateur d’indirection retourne *get()
. Par conséquent, le pointeur stocké ne doit pas être null.
Exemple
// std__memory__shared_ptr_operator_st.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp0(new int(5));
std::cout << "*sp0 == " << *sp0 << std::endl;
return (0);
}
*sp0 == 5
operator=
Remplace la ressource détenue.
shared_ptr& operator=(const shared_ptr& sp) noexcept;
shared_ptr& operator=(shared_ptr&& sp) noexcept;
template <class Other>
shared_ptr& operator=(const shared_ptr<Other>& sp) noexcept;
template <class Other>
shared_ptr& operator=(shared_ptr<Other>&& sp) noexcept;
template <class Other>
shared_ptr& operator=(auto_ptr<Other>&& ap); // deprecated in C++11, removed in C++17
template <class Other, class Deleter>
shared_ptr& operator=(unique_ptr<Other, Deleter>&& up);
Paramètres
sp
Pointeur partagé à partir duquel copier ou passer.
ap
Pointeur automatique à déplacer. La auto_ptr
surcharge est déconseillée en C++11 et supprimée en C++17.
up
Pointeur unique vers l’objet à adopter la propriété. up
ne possède aucun objet après l’appel.
Other
Type de l’objet pointé par sp
, ap
ou up
.
Deleter
Type du deleter de l’objet appartenant, stocké pour la suppression ultérieure de l’objet.
Notes
Tous les opérateurs décrémentent le nombre de références pour la ressource actuellement détenue par *this
et assignent la propriété de la ressource nommée par la séquence d’opérandes à *this
. Si le nombre de références atteint zéro, la ressource est libérée. En cas d’échec d’un opérateur, il reste *this
inchangé.
Exemple
// std__memory__shared_ptr_operator_as.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp0;
std::shared_ptr<int> sp1(new int(5));
std::unique_ptr<int> up(new int(10));
sp0 = sp1;
std::cout << "*sp0 == " << *sp0 << std::endl;
sp0 = up;
std::cout << "*sp0 == " << *sp0 << std::endl;
return (0);
}
*sp0 == 5
*sp0 == 10
operator->
Obtient un pointeur vers la valeur désignée.
T* operator->() const noexcept;
Notes
L’opérateur de sélection retourne get()
de sorte que l’expression sp->member
se comporte comme (sp.get())->member
, où sp
est un objet de la classe shared_ptr<T>
. Le pointeur stocké ne doit donc pas être Null, et T
doit être une classe, une structure ou une union avec un membre member
.
Exemple
// std__memory__shared_ptr_operator_ar.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
typedef std::pair<int, int> Mypair;
int main()
{
std::shared_ptr<Mypair> sp0(new Mypair(1, 2));
std::cout << "sp0->first == " << sp0->first << std::endl;
std::cout << "sp0->second == " << sp0->second << std::endl;
return (0);
}
sp0->first == 1
sp0->second == 2
owner_before
Retourne true si ce shared_ptr
est classé avant le pointeur fourni (ou est inférieur à celui-ci).
template <class Other>
bool owner_before(const shared_ptr<Other>& ptr) const noexcept;
template <class Other>
bool owner_before(const weak_ptr<Other>& ptr) const noexcept;
Paramètres
ptr
Référence lvalue à un shared_ptr
ou un weak_ptr
.
Notes
La fonction membre du modèle retourne la valeur true si *this
elle est ordonnée avant ptr
.
reset
Remplacer la ressource détenue.
void reset() noexcept;
template <class Other>
void reset(Other *ptr);
template <class Other, class Deleter>
void reset(
Other *ptr,
Deleter deleter);
template <class Other, class Deleter, class Allocator>
void reset(
Other *ptr,
Deleter deleter,
Allocator alloc);
Paramètres
Other
Type contrôlé par le pointeur d’argument.
Deleter
Type du suppresseur.
ptr
Pointeur à copier.
deleter
Suppresseur à copier.
Allocator
Type de l'allocateur.
alloc
Allocateur à copier.
Notes
Tous les opérateurs décrémentent le nombre de références pour la ressource actuellement détenue par *this
et assignent la propriété de la ressource nommée par la séquence d’opérandes à *this
. Si le nombre de références atteint zéro, la ressource est libérée. En cas d’échec d’un opérateur, il reste *this
inchangé.
Exemple
// std__memory__shared_ptr_reset.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
struct deleter
{
void operator()(int *p)
{
delete p;
}
};
int main()
{
std::shared_ptr<int> sp(new int(5));
std::cout << "*sp == " << std::boolalpha
<< *sp << std::endl;
sp.reset();
std::cout << "(bool)sp == " << std::boolalpha
<< (bool)sp << std::endl;
sp.reset(new int(10));
std::cout << "*sp == " << std::boolalpha
<< *sp << std::endl;
sp.reset(new int(15), deleter());
std::cout << "*sp == " << std::boolalpha
<< *sp << std::endl;
return (0);
}
*sp == 5
(bool)sp == false
*sp == 10
*sp == 15
shared_ptr
Construit un objet shared_ptr
.
constexpr shared_ptr() noexcept;
constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() {}
shared_ptr(const shared_ptr& sp) noexcept;
shared_ptr(shared_ptr&& sp) noexcept;
template <class Other>
explicit shared_ptr(Other* ptr);
template <class Other, class Deleter>
shared_ptr(
Other* ptr,
Deleter deleter);
template <class Deleter>
shared_ptr(
nullptr_t ptr,
Deleter deleter);
template <class Other, class Deleter, class Allocator>
shared_ptr(
Other* ptr,
Deleter deleter,
Allocator alloc);
template <class Deleter, class Allocator>
shared_ptr(
nullptr_t ptr,
Deleter deleter,
Allocator alloc);
template <class Other>
shared_ptr(
const shared_ptr<Other>& sp) noexcept;
template <class Other>
explicit shared_ptr(
const weak_ptr<Other>& wp);
template <class &>
shared_ptr(
std::auto_ptr<Other>& ap);
template <class &>
shared_ptr(
std::auto_ptr<Other>&& ap);
template <class Other, class Deleter>
shared_ptr(
unique_ptr<Other, Deleter>&& up);
template <class Other>
shared_ptr(
const shared_ptr<Other>& sp,
element_type* ptr) noexcept;
template <class Other>
shared_ptr(
shared_ptr<Other>&& sp,
element_type* ptr) noexcept;
template <class Other, class Deleter>
shared_ptr(
const unique_ptr<Other, Deleter>& up) = delete;
Paramètres
Other
Type contrôlé par le pointeur d’argument.
ptr
Pointeur à copier.
Deleter
Type du suppresseur.
Allocator
Type de l'allocateur.
deleter
Suppresseur.
alloc
Allocateur.
sp
Pointeur intelligent à copier.
wp
Pointeur faible.
ap
Pointeur automatique à copier.
Notes
Chaque constructeur construit un objet qui possède la ressource nommée par la séquence d’opérandes. Le constructeur shared_ptr(const weak_ptr<Other>& wp)
lève un objet d’exception de type bad_weak_ptr
si wp.expired()
.
Exemple
// std__memory__shared_ptr_construct.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
struct deleter
{
void operator()(int *p)
{
delete p;
}
};
int main()
{
std::shared_ptr<int> sp0;
std::cout << "(bool)sp0 == " << std::boolalpha
<< (bool)sp0 << std::endl;
std::shared_ptr<int> sp1(new int(5));
std::cout << "*sp1 == " << *sp1 << std::endl;
std::shared_ptr<int> sp2(new int(10), deleter());
std::cout << "*sp2 == " << *sp2 << std::endl;
std::shared_ptr<int> sp3(sp2);
std::cout << "*sp3 == " << *sp3 << std::endl;
std::weak_ptr<int> wp(sp3);
std::shared_ptr<int> sp4(wp);
std::cout << "*sp4 == " << *sp4 << std::endl;
std::auto_ptr<int> ap(new int(15));
std::shared_ptr<int> sp5(ap);
std::cout << "*sp5 == " << *sp5 << std::endl;
return (0);
}
(bool)sp0 == false
*sp1 == 5
*sp2 == 10
*sp3 == 10
*sp4 == 10
*sp5 == 15
~shared_ptr
Détruit un shared_ptr
.
~shared_ptr();
Notes
Le destructeur décrémente le nombre de références pour la ressource actuellement détenue par *this
. Si le nombre de références atteint zéro, la ressource est libérée.
Exemple
// std__memory__shared_ptr_destroy.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp1(new int(5));
std::cout << "*sp1 == " << *sp1 << std::endl;
std::cout << "use count == " << sp1.use_count() << std::endl;
{
std::shared_ptr<int> sp2(sp1);
std::cout << "*sp2 == " << *sp2 << std::endl;
std::cout << "use count == " << sp1.use_count() << std::endl;
}
// check use count after sp2 is destroyed
std::cout << "use count == " << sp1.use_count() << std::endl;
return (0);
}
*sp1 == 5
use count == 1
*sp2 == 5
use count == 2
use count == 1
swap
Échange deux objets shared_ptr
.
void swap(shared_ptr& sp) noexcept;
Paramètres
sp
Pointeur partagé à échanger.
Notes
La fonction membre laisse la ressource détenue à l’origine par *this
devenir la propriété de sp
, et la ressource détenue à l’origine par sp
devenir la propriété de *this
. La fonction ne modifie pas le nombre de références pour les deux ressources et ne lève aucune exception.
Exemple
// std__memory__shared_ptr_swap.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp1(new int(5));
std::shared_ptr<int> sp2(new int(10));
std::cout << "*sp1 == " << *sp1 << std::endl;
sp1.swap(sp2);
std::cout << "*sp1 == " << *sp1 << std::endl;
swap(sp1, sp2);
std::cout << "*sp1 == " << *sp1 << std::endl;
std::cout << std::endl;
std::weak_ptr<int> wp1(sp1);
std::weak_ptr<int> wp2(sp2);
std::cout << "*wp1 == " << *wp1.lock() << std::endl;
wp1.swap(wp2);
std::cout << "*wp1 == " << *wp1.lock() << std::endl;
swap(wp1, wp2);
std::cout << "*wp1 == " << *wp1.lock() << std::endl;
return (0);
}
*sp1 == 5
*sp1 == 10
*sp1 == 5
*wp1 == 5
*wp1 == 10
*wp1 == 5
unique
Teste si la ressource détenue est unique. Cette fonction a été déconseillée en C++17 et supprimée en C++20.
bool unique() const noexcept;
Notes
La fonction membre retourne true
si aucun autre objet shared_ptr
détient la ressource qui appartient à *this
. Sinon, elle retourne false
.
Exemple
// std__memory__shared_ptr_unique.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp1(new int(5));
std::cout << "sp1.unique() == " << std::boolalpha
<< sp1.unique() << std::endl;
std::shared_ptr<int> sp2(sp1);
std::cout << "sp1.unique() == " << std::boolalpha
<< sp1.unique() << std::endl;
return (0);
}
sp1.unique() == true
sp1.unique() == false
use_count
Compte le nombre de propriétaires de ressources.
long use_count() const noexcept;
Notes
La fonction membre retourne le nombre d’objets shared_ptr
qui détiennent la ressource appartenant à *this
.
Exemple
// std__memory__shared_ptr_use_count.cpp
// compile with: /EHsc
#include <memory>
#include <iostream>
int main()
{
std::shared_ptr<int> sp1(new int(5));
std::cout << "sp1.use_count() == "
<< sp1.use_count() << std::endl;
std::shared_ptr<int> sp2(sp1);
std::cout << "sp1.use_count() == "
<< sp1.use_count() << std::endl;
return (0);
}
sp1.use_count() == 1
sp1.use_count() == 2
weak_type
Type d’un pointeur faible vers un élément.
using weak_type = weak_ptr<T>; // C++17
Notes
La weak_type
définition a été ajoutée en C++17.
Voir aussi
Informations de référence sur les fichiers d’en-tête
<memory>
unique_ptr
weak_ptr
, classe