Classe shared_ptr
Encapsula um ponteiro inteligente de contagem de referência em torno de um objeto alocado dinamicamente.
Sintaxe
template <class T>
class shared_ptr;
Comentários
A classe shared_ptr
descreve um objeto que usa contagem de referências para gerenciar recursos. Um objeto shared_ptr
contém efetivamente um ponteiro para o recurso que esse objeto possui ou então retém um ponteiro nulo. Um recurso pode ser possuído por mais um objeto shared_ptr
; quando o último objeto shared_ptr
que possui um recurso específico é destruído, o recurso é liberado.
Um shared_ptr
deixa de possuir um recurso quando ele é reatribuído ou redefinido.
O argumento de modelo T
pode ser um tipo incompleto, exceto como observado para determinadas funções membro.
Quando um objeto shared_ptr<T>
é criado com base em de um ponteiro de recurso do tipo G*
ou com base em um shared_ptr<G>
, o tipo de ponteiro G*
deve poder ser convertido para T*
. Se ele não for conversível, o código não será compilado. Por exemplo:
#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>
Um objeto shared_ptr
possui um recurso:
se ele foi criado com um ponteiro para esse recurso,
se ele foi criado com um objeto
shared_ptr
que possui esse recurso,se ele foi criado com um objeto
weak_ptr
que aponta para esse recurso, ouse a propriedade desse recurso foi atribuída a ele, seja com
shared_ptr::operator=
ou chamando a função membroshared_ptr::reset
.
Os objetos shared_ptr
que possuem um recurso compartilham um bloco de controle. O bloco de controle contém:
o número de objetos
shared_ptr
que são proprietários do recurso,o número de objetos
weak_ptr
que apontam para o recurso,o agente de exclusão para esse recurso, se houver,
o alocador personalizado para o bloco de controle, se houver.
Um objeto shared_ptr
que é inicializado pelo uso de um ponteiro nulo tem um bloco de controle de objeto e não está vazio. Após um objeto shared_ptr
liberar um recurso, ele não possui mais esse recurso. Após um objeto weak_ptr
liberar um recurso, ele não aponta mais para esse recurso.
Quando o número de objetos shared_ptr
que possuem um recurso se torna zero, o recurso é liberado, excluindo-o ou passando o seu endereço para um agente de exclusão, dependendo de como a propriedade do recurso foi originalmente criada. Quando o número de objetos shared_ptr
que possuem um recurso é zero e o número de objetos weak_ptr
que apontam para esse recurso é zero, o bloco de controle é liberado, usando o alocador personalizado para o bloco de controle se ele tiver um.
Um objeto shared_ptr
vazio não possui recursos e não tem nenhum bloco de controle.
Um agente de exclusão é um objeto de função que tem uma função membro operator()
. Seu tipo deve ser construível por cópia e seu construtor e destruidor de cópia não devem gerar exceções. Ele aceita um parâmetro, o objeto a ser excluído.
Algumas funções usam uma lista de argumentos que define propriedades do objeto shared_ptr<T>
ou weak_ptr<T>
resultante. É possível especificar essa lista de argumentos de várias maneiras:
sem argumentos: o objeto resultante é um ou objeto shared_ptr
vazio ou um objeto weak_ptr
vazio.
ptr
: um ponteiro de tipo Other*
para o recurso a ser gerenciado. T
deve ser um tipo completo. Se a função falhar (por não ser possível alocar o bloco de controle) ela avaliará a expressão delete ptr
.
ptr, deleter
: um ponteiro de tipo Other*
para o recurso a ser gerenciado e um agente de exclusão para esse recurso. Se a função falhar (por não ser possível alocar o bloco de controle) ela chamará deleter(ptr)
, que precisará ser bem definido.
ptr, deleter, alloc
: um ponteiro de tipo Other*
para o recurso a ser gerenciado, um agente de exclusão para esse recurso e um alocador para gerenciar qualquer armazenamento que precise ser alocado e liberado. Se a função falhar (por não ser possível alocar o bloco de controle) ela chamará deleter(ptr)
, que precisará ser bem definido.
sp
: um objeto shared_ptr<Other>
que possui o recurso a ser gerenciado.
wp
: um objeto weak_ptr<Other>
que aponta para o recurso a ser gerenciado.
ap
: um objeto auto_ptr<Other>
que retém um ponteiro para o recurso a ser gerenciado. Se a função obtiver êxito ela chamará ap.release()
; caso contrário, ela deixará ap
inalterado.
Em todos os casos, o tipo de ponteiro Other*
deve poder ser convertido para T*
.
Acesso thread-safe
Vários threads podem ler e gravar simultaneamente objetos shared_ptr
diferentes, mesmo quando os objetos são cópias que compartilham a propriedade.
Membros
Nome | Descrição |
---|---|
Construtores | |
shared_ptr |
Constrói um shared_ptr . |
~shared_ptr |
Destrói um shared_ptr . |
Typedefs | |
element_type |
O tipo de um elemento. |
weak_type |
O tipo de um ponteiro fraco para um elemento. |
Funções de membro | |
get |
Obtém o endereço do recurso possuído. |
owner_before |
Retornará true se este shared_ptr estiver ordenado antes do (ou for inferior ao) ponteiro fornecido. |
reset |
Substitua o recurso possuído. |
swap |
Troca dois objetos shared_ptr . |
unique |
Testa se o recurso possuído é exclusivo. |
use_count |
Conta números de proprietários de recurso. |
Operadores | |
operator bool |
Testa se um recurso possuído existe. |
operator* |
Obtém o valor designado. |
operator= |
Substitui o recurso possuído. |
operator-> |
Obtém um ponteiro para o valor designado. |
element_type
O tipo de um elemento.
typedef T element_type; // before C++17
using element_type = remove_extent_t<T>; // C++17
Comentários
O tipo element_type
é um sinônimo do parâmetro de modelo T
.
Exemplo
// 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
Obtém o endereço do recurso possuído.
element_type* get() const noexcept;
Comentários
A função membro retorna o endereço do recurso possuído. Se o objeto não possuir um recurso, ela retornará 0.
Exemplo
// 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
Testa se um recurso possuído existe.
explicit operator bool() const noexcept;
Comentários
O operador retorna um valor de true
quando get() != nullptr
, caso contrário false
.
Exemplo
// 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*
Obtém o valor designado.
T& operator*() const noexcept;
Comentários
O operador de indireção retorna *get()
. Portanto, o ponteiro armazenado não deve ser nulo.
Exemplo
// 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=
Substitui o recurso possuído.
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);
Parâmetros
sp
O ponteiro compartilhado do qual copiar ou mover.
ap
O ponteiro automático para mover. A sobrecarga auto_ptr
foi preterida em C++11 e removida em C++17.
up
O ponteiro exclusivo para o objeto do qual adotar a propriedade. up
não possui nenhum objeto após a chamada.
Other
O tipo do objeto apontado por sp
, ap
ou up
.
Deleter
O tipo do agente de exclusão do objeto de propriedade, armazenado para exclusão posterior do objeto.
Comentários
Todos os operadores decrementam a contagem de referência para o recurso pertencente a *this
e atribuem a propriedade do recurso nomeado pela sequência de operandos para *this
. Se a contagem de referência cai para zero, o recurso é liberado. Se um operador falhar, ele deixará *this
inalterado.
Exemplo
// 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->
Obtém um ponteiro para o valor designado.
T* operator->() const noexcept;
Comentários
O operador de seleção retorna get()
, de modo que a expressão sp->member
comporta-se da mesma forma que (sp.get())->member
, em que sp
é um objeto da classe shared_ptr<T>
. Portanto, o ponteiro armazenado não deve ser nulo e o T
deve ser uma classe, estrutura ou tipo de união com um membro member
.
Exemplo
// 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
Retornará true se este shared_ptr
estiver ordenado antes do (ou for inferior ao) ponteiro fornecido.
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;
Parâmetros
ptr
Uma referência lvalue para um shared_ptr
ou um weak_ptr
.
Comentários
A função membro do modelo retornará true se *this
for ordenado antes de ptr
.
reset
Substitua o recurso possuído.
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);
Parâmetros
Other
O tipo controlado pelo ponteiro de argumento.
Deleter
O tipo do agente de exclusão.
ptr
O ponteiro para copiar.
deleter
O agente de exclusão a copiar.
Allocator
O tipo do alocador.
alloc
O alocador a copiar.
Comentários
Todos os operadores decrementam a contagem de referência para o recurso pertencente a *this
e atribuem a propriedade do recurso nomeado pela sequência de operandos para *this
. Se a contagem de referência cai para zero, o recurso é liberado. Se um operador falhar, ele deixará *this
inalterado.
Exemplo
// 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
Constrói um 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;
Parâmetros
Other
O tipo controlado pelo ponteiro de argumento.
ptr
O ponteiro para copiar.
Deleter
O tipo do agente de exclusão.
Allocator
O tipo do alocador.
deleter
O agente de exclusão.
alloc
O alocador.
sp
O ponteiro inteligente a copiar.
wp
O ponteiro fraco.
ap
O ponteiro automático para copiar.
Comentários
Cada um dos construtores cria um objeto que possui o recurso nomeado pela sequência de operandos. O construtor shared_ptr(const weak_ptr<Other>& wp)
gera um objeto de exceção do tipo bad_weak_ptr
se wp.expired()
.
Exemplo
// 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
Destrói um shared_ptr
.
~shared_ptr();
Comentários
O destruidor decrementa a contagem de referência para o recurso atualmente pertencente a *this
. Se a contagem de referência cai para zero, o recurso é liberado.
Exemplo
// 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
Troca dois objetos shared_ptr
.
void swap(shared_ptr& sp) noexcept;
Parâmetros
sp
O ponteiro compartilhado com o qual realizar a troca.
Comentários
A função membro deixa o recurso originalmente possuído por *this
e subsequentemente possuído por sp
e o recurso originalmente possuído por sp
subsequentemente possuído por *this
. A função não altera as contagens de referências dos dois recursos e ela não gera exceções.
Exemplo
// 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
Testa se o recurso possuído é exclusivo. Essa função foi preterida em C++17 e removida em C++20.
bool unique() const noexcept;
Comentários
A função membro retorna true
se nenhum outro objeto shared_ptr
possui o recurso que pertence a *this
, caso contrário, false
.
Exemplo
// 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 números de proprietários de recurso.
long use_count() const noexcept;
Comentários
A função membro retorna o número de objetos shared_ptr
que tem do recurso que pertence a *this
.
Exemplo
// 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
O tipo de um ponteiro fraco para um elemento.
using weak_type = weak_ptr<T>; // C++17
Comentários
A definição weak_type
foi adicionada em C++17.
Confira também
Referência de Arquivos de Cabeçalho
<memory>
unique_ptr
weak_ptr
classe