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, ou

  • si la propriété de cette ressource a été affectée, avec shared_ptr::operator= ou en appelant la fonction shared_ptr::resetmembre.

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 Tde 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, apou 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