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 ose la proprietà di tale risorsa è stata assegnata, con
shared_ptr::operator=
o chiamando la funzioneshared_ptr::reset
membro .
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.
sp
shared_ptr<Other>
: oggetto proprietario della risorsa da gestire.
wp
weak_ptr<Other>
: oggetto che punta alla risorsa da gestire.
ap
auto_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 T
di 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 sp
cui punta , ap
o 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 ptr
di .
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