Procuro entender como std::unique_ptr
funciona e para isso encontrei este documento. O autor parte do seguinte exemplo:
#include <utility> //declarations of unique_ptr
using std::unique_ptr;
// default construction
unique_ptr<int> up; //creates an empty object
// initialize with an argument
unique_ptr<int> uptr (new int(3));
double *pd= new double;
unique_ptr<double> uptr2 (pd);
// overloaded * and ->
*uptr2 = 23.5;
unique_ptr<std::string> ups (new std::string("hello"));
int len=ups->size();
O que é confuso para mim é que nesta linha
unique_ptr<int> uptr (new int(3));
Usamos inteiro como argumento (entre colchetes) e aqui
unique_ptr<double> uptr2 (pd);
usamos um ponteiro como argumento. Isso faz alguma diferença?
O que também não está claro para mim é como os ponteiros, declarados dessa forma, serão diferentes dos ponteiros declarados de forma "normal".
c++
pointers
std
unique-ptr
romano
fonte
fonte
new int(3)
retorna um ponteiro para o novoint
, assim comopd
um ponteiro para o novodouble
.Respostas:
O construtor de
unique_ptr<T>
aceita um ponteiro bruto para um objeto do tipoT
(portanto, ele aceita aT*
).No primeiro exemplo:
O ponteiro é o resultado de uma
new
expressão, enquanto no segundo exemplo:O ponteiro é armazenado na
pd
variável.Conceitualmente, nada muda (você está construindo um a
unique_ptr
partir de um ponteiro bruto), mas a segunda abordagem é potencialmente mais perigosa, pois permitiria a você, por exemplo, fazer:Assim, temos dois ponteiros únicos que efetivamente encapsulam o mesmo objeto (violando assim a semântica de um ponteiro único ).
É por isso que a primeira forma de criar um ponteiro exclusivo é melhor, quando possível. Observe que em C ++ 14 seremos capazes de fazer:
O que é mais claro e seguro. Agora, a respeito dessa sua dúvida:
Supõe-se que os ponteiros inteligentes modelem a propriedade do objeto e automaticamente cuidem da destruição do objeto apontado quando o último ponteiro (inteligente, proprietário) para esse objeto sair do escopo.
Desta forma, você não precisa se lembrar de fazer
delete
em objetos alocados dinamicamente - o destruidor do ponteiro inteligente fará isso por você - nem se preocupar se você não cancelará a referência de um ponteiro (pendente) para um objeto que já foi destruído:Agora
unique_ptr
é um ponteiro inteligente que modela a propriedade exclusiva, o que significa que a qualquer momento em seu programa deve haver apenas um ponteiro (proprietário) para o objeto apontado - é por isso queunique_ptr
não pode ser copiado.Contanto que você use ponteiros inteligentes de uma maneira que não quebre o contrato implícito que eles exigem que você cumpra, você terá a garantia de que nenhuma memória será perdida e a política de propriedade adequada para seu objeto será aplicada. Ponteiros brutos não oferecem essa garantia.
fonte
model object ownership
ointeger leak
no código ouenforcing ownership policy for object
. Você poderia sugerir tópicos / recursos para aprender esses conceitos?unique_ptr
, sem obter um erroThe text ">" is unexpected. It may be that this token was intended as a template argument list terminator but the name is not known to be a template.
:, embora tenha#include <utility>
e#include <memory>
. Algum conselho?Não há diferença em trabalhar em ambos os conceitos de atribuição a unique_ptr.
é similar a
Aqui unique_ptr exclui automaticamente o espaço ocupado por
uptr
.Se você criar um inteiro no espaço de heap (usando nova palavra-chave ou malloc ), você terá que limpar essa memória sozinho (usando delete ou free respectivamente).
No código abaixo,
Aqui, você terá que excluir heapInt, quando terminar de usar. Se não for excluído, ocorre vazamento de memória.
Para evitar esses vazamentos de memória, unique_ptr é usado, onde unique_ptr exclui automaticamente o espaço ocupado por heapInt quando ele sai do escopo. Portanto, você não precisa excluir ou liberar para unique_ptr.
fonte
Ponteiros exclusivos garantem a destruição do objeto que gerenciam quando saem do escopo. http://en.cppreference.com/w/cpp/memory/unique_ptr
Nesse caso:
pd
será destruído quandouptr2
sai do escopo. Isso facilita o gerenciamento de memória por exclusão automática.O caso de
unique_ptr<int> uptr (new int(3));
não é diferente, exceto que o ponteiro bruto não é atribuído a nenhuma variável aqui.fonte
De cppreference , um dos
std::unique_ptr
construtores éUnique_ptr explícito (ponteiro p) noexcept;
Portanto, criar um novo
std::unique_ptr
é passar um ponteiro para seu construtor.Ou é o mesmo que
A diferença é que você não precisa limpar depois de usá-lo. Se você não usar
std::unique_ptr
(ponteiro inteligente), você terá que excluí-lo assimquando você não precisar mais dele ou causará um vazamento de memória.
fonte