Classe shared_ptr

Esegue il wrapping di un puntatore intelligente con conteggio dei riferimenti attorno a un oggetto allocato in modo dinamico.

Sintassi

template <class T>
class shared_ptr;

Osservazioni:

La shared_ptr classe descrive un oggetto che utilizza il conteggio dei riferimenti per gestire le risorse. Un oggetto shared_ptr contiene efficacemente un puntatore a una risorsa che contiene un puntatore null. Una risorsa può appartenere a non più di un oggetto shared_ptr. Quando un oggetto shared_ptr proprietario di una risorsa particolare viene eliminato, la risorsa viene liberata.

Un shared_ptr oggetto smette di possedere una risorsa quando viene riassegnato o reimpostato.

Un argomento di modello T potrebbe essere un tipo incompleto ad eccezione di quanto indicato per determinate funzioni membro.

Quando un oggetto shared_ptr<T> viene costruito da un puntatore di risorse di tipo G* o shared_ptr<G>, il tipo di puntatore G* deve essere convertibile in T*. Se non è convertibile, il codice non verrà compilato. Ad esempio:

#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 oggetto shared_ptr possiede una risorsa nei casi seguenti:

  • se viene costruito con un puntatore alla risorsa,

  • se è stato creato da un oggetto shared_ptr proprietario della risorsa,

  • se è stato costruito da un weak_ptr oggetto che punta a tale risorsa o

  • se la proprietà di tale risorsa è stata assegnata, con shared_ptr::operator= o chiamando la funzione shared_ptr::resetmembro .

Gli oggetti shared_ptr che possiedono una risorsa condividono un blocco di controllo. Il blocco di controllo contiene gli elementi seguenti:

  • numero di oggetti shared_ptr che possiedono la risorsa,

  • numero di oggetti weak_ptr che puntano alla risorsa,

  • metodo Deleter per tale risorsa (se disponibile),

  • allocatore personalizzato per un blocco di controllo (se presente).

Un shared_ptr oggetto inizializzato tramite un puntatore Null ha un blocco di controllo e non è vuoto. Dopo che un oggetto shared_ptr rilascia una risorsa, non possiede più tale risorsa. Dopo che un oggetto weak_ptr rilascia una risorsa, non punta più a tale risorsa.

Quando il numero di oggetti shared_ptr che possiedono una risorsa diventa zero, la risorsa viene liberata, eliminandola o passandone l'indirizzo a un metodo Deleter, in base al modo in cui la proprietà della risorsa è stata inizialmente creata. Quando il numero di oggetti shared_ptr che possiedono una risorsa è zero e il numero di oggetti weak_ptr che puntano a tale risorsa è zero, il blocco di controllo viene liberato, utilizzando l'allocatore personalizzato per un blocco di controllo (se presente).

Un oggetto vuoto shared_ptr non è proprietario di alcuna risorsa e non dispone di alcun blocco di controllo.

Un metodo Deleter è un oggetto funzione con una funzione membro operator(). Il tipo deve essere costruibile per copia e i relativi costruttore copia e distruttore copia non devono generare eccezioni. Accetta un parametro, ovvero l'oggetto da eliminare.

Alcune funzioni accettano un elenco di argomenti che definiscono le proprietà dell'oggetto shared_ptr<T> risultante o dell'oggetto weak_ptr<T>. È possibile specificare tale elenco di argomenti in diversi modi:

nessun argomento: l'oggetto risultante è un oggetto vuoto shared_ptr o un oggetto vuoto weak_ptr .

ptr: puntatore di tipo Other* alla risorsa da gestire. L'oggetto T deve essere un tipo completo. Se la funzione ha esito negativo (perché il blocco di controllo non può essere allocato), valuta l'espressione delete ptr.

ptr, deleter: puntatore di tipo Other* alla risorsa da gestire e un deleter per tale risorsa. Se la funzione ha esito negativo (perché il blocco di controllo non può essere allocato), chiama deleter(ptr), che deve essere ben definito.

ptr, deleter, alloc: puntatore di tipo Other* alla risorsa da gestire, un deleter per tale risorsa e un allocatore per gestire qualsiasi risorsa di archiviazione che deve essere allocata e liberata. Se la funzione ha esito negativo (perché il blocco di controllo non può essere allocato), chiama deleter(ptr), che deve essere ben definito.

spshared_ptr<Other>: oggetto proprietario della risorsa da gestire.

wpweak_ptr<Other>: oggetto che punta alla risorsa da gestire.

apauto_ptr<Other>: oggetto che contiene un puntatore alla risorsa da gestire. Se la funzione ha esito positivo, chiama ap.release(); in caso contrario, rimane ap invariata.

In tutti i casi, il tipo di puntatore Other* deve essere convertibile in T*.

Thread safety

Più thread possono leggere e scrivere contemporaneamente oggetti shared_ptr diversi, anche se gli oggetti sono copie che ne condividono la proprietà.

Membri

Nome Descrizione
Costruttori
shared_ptr Costruisce un oggetto shared_ptr.
~shared_ptr Elimina un oggetto shared_ptr.
Typedef
element_type Tipo di un elemento.
weak_type Tipo di puntatore debole a un elemento.
Funzioni membro
get Ottiene l'indirizzo della risorsa posseduta.
owner_before Restituisce true se shared_ptr è ordinato in posizione precedente (o è minore di) del puntatore fornito.
reset Sostituisce una risorsa di proprietà.
swap Scambia due oggetti shared_ptr.
unique Verifica se la risorsa di proprietà è univoca.
use_count Conta il numero dei proprietari delle risorse.
Operatori
operator bool Verifica se una risorsa di proprietà esiste.
operator* Ottiene il valore definito.
operator= Sostituisce la risorsa di proprietà.
operator-> Ottiene un puntatore al valore definito.

element_type

Tipo di un elemento.

typedef T element_type;                  // before C++17
using element_type = remove_extent_t<T>; // C++17

Osservazioni:

Il element_type tipo è un sinonimo del parametro Tdi modello .

Esempio

// 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

Ottiene l'indirizzo della risorsa posseduta.

element_type* get() const noexcept;

Osservazioni:

La funzione membro restituisce l'indirizzo della risorsa posseduta. Se l'oggetto non è proprietario di una risorsa, restituisce 0.

Esempio

// 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

Verifica se una risorsa di proprietà esiste.

explicit operator bool() const noexcept;

Osservazioni:

L'operatore restituisce un valore di true quando get() != nullptr, in caso contrario false.

Esempio

// 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*

Ottiene il valore definito.

T& operator*() const noexcept;

Osservazioni:

L'operatore di riferimento indiretto restituisce *get(). Di conseguenza, il puntatore archiviato non deve essere null.

Esempio

// 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=

Sostituisce la risorsa di proprietà.

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);

Parametri

sp
Puntatore condiviso da cui copiare o spostare.

ap
Puntatore automatico da spostare. L'overload auto_ptr è deprecato in C++11 e rimosso in C++17.

up
Puntatore univoco all'oggetto di cui adottare la proprietà. up non possiede alcun oggetto dopo la chiamata.

Other
Tipo dell'oggetto a spcui punta , apo up.

Deleter
Tipo dell'deleter dell'oggetto di proprietà, archiviato per un'eliminazione successiva dell'oggetto.

Osservazioni:

Tutti gli operatori riducono il numero dei riferimenti per la risorsa attualmente di proprietà di *this e assegnano a *this la proprietà della risorsa descritta dalla sequenza di operandi. Se il conteggio dei riferimenti scende a zero, la risorsa viene rilasciata. Se un operatore non riesce, rimane *this invariato.

Esempio

// 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->

Ottiene un puntatore al valore definito.

T* operator->() const noexcept;

Osservazioni:

L'operatore di selezione restituisce get(), in modo che l'espressione sp->member si comporti come (sp.get())->member dove sp è un oggetto di classe shared_ptr<T>. Di conseguenza, il puntatore archiviato non deve essere null e T deve essere una classe, una struttura o un tipo di unione con un membro member.

Esempio

// 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

Restituisce true se shared_ptr è ordinato in posizione precedente (o è minore di) del puntatore fornito.

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;

Parametri

ptr
Riferimento lvalue a un shared_ptr oggetto o a .weak_ptr

Osservazioni:

La funzione membro del modello restituisce true se *this è ordinato prima ptrdi .

reset

Sostituisce una risorsa di proprietà.

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);

Parametri

Other
Tipo controllato dal puntatore argomento.

Deleter
Tipo del metodo Deleter.

ptr
Puntatore da copiare.

deleter
Metodo Deleter da copiare.

Allocator
Tipo dell'allocatore.

alloc
Allocatore da copiare.

Osservazioni:

Tutti gli operatori riducono il numero dei riferimenti per la risorsa attualmente di proprietà di *this e assegnano a *this la proprietà della risorsa descritta dalla sequenza di operandi. Se il conteggio dei riferimenti scende a zero, la risorsa viene rilasciata. Se un operatore non riesce, rimane *this invariato.

Esempio

// 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

Costruisce un oggetto 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;

Parametri

Other
Tipo controllato dal puntatore argomento.

ptr
Puntatore da copiare.

Deleter
Tipo del metodo Deleter.

Allocator
Tipo dell'allocatore.

deleter
Metodo Deleter.

alloc
Allocatore.

sp
Puntatore intelligente da copiare.

wp
Puntatore debole.

ap
Puntatore automatico da copiare.

Osservazioni:

Ogni costruttore crea un oggetto che possiede la risorsa descritta dalla sequenza di operandi. Il costruttore shared_ptr(const weak_ptr<Other>& wp) genera un oggetto eccezione di tipo bad_weak_ptr se wp.expired().

Esempio

// 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

Elimina un oggetto shared_ptr.

~shared_ptr();

Osservazioni:

Il distruttore riduce il numero di riferimenti per la risorsa attualmente di proprietà di *this. Se il conteggio dei riferimenti scende a zero, la risorsa viene rilasciata.

Esempio

// 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

Scambia due oggetti shared_ptr.

void swap(shared_ptr& sp) noexcept;

Parametri

sp
Puntatore condiviso con cui effettuare lo scambio.

Osservazioni:

La funzione membro lascia che la risorsa originariamente di proprietà di *this divenga in seguito di proprietà di sp e che la risorsa originariamente di proprietà di sp divenga in seguito di proprietà di *this. La funzione non modifica i conteggi dei riferimenti per le due risorse e non genera eccezioni.

Esempio

// 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

Verifica se la risorsa di proprietà è univoca. Questa funzione è stata deprecata in C++17 e rimossa in C++20.

bool unique() const noexcept;

Osservazioni:

La funzione membro restituisce true se nessun altro oggetto shared_ptr possiede la risorsa di proprietà di *this; in caso contrario, restituisce false.

Esempio

// 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

Conta il numero dei proprietari delle risorse.

long use_count() const noexcept;

Osservazioni:

La funzione membro restituisce il numero di oggetti shared_ptr che possiedono la risorsa di proprietà di *this.

Esempio

// 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

Tipo di puntatore debole a un elemento.

using weak_type = weak_ptr<T>; // C++17

Osservazioni:

La weak_type definizione è stata aggiunta in C++17.

Vedi anche

Riferimento file di intestazione
<memory>
unique_ptr
Classe weak_ptr