Intento entender cómo std::unique_ptr
funciona y para eso encontré este documento. El autor parte del siguiente ejemplo:
#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();
Lo que me confunde es que en esta línea
unique_ptr<int> uptr (new int(3));
Usamos integer como argumento (entre paréntesis) y aquí
unique_ptr<double> uptr2 (pd);
utilizamos un puntero como argumento. ¿Hace alguna diferencia?
Lo que tampoco me queda claro es cómo los punteros, declarados de esta manera, serán diferentes de los punteros declarados de una manera "normal".
c++
pointers
std
unique-ptr
romano
fuente
fuente
new int(3)
devuelve un puntero al nuevoint
, como sipd
fuera un puntero al nuevodouble
.Respuestas:
El constructor de
unique_ptr<T>
acepta un puntero sin formato a un objeto de tipoT
(por lo tanto, acepta aT*
).En el primer ejemplo:
unique_ptr<int> uptr (new int(3));
El puntero es el resultado de una
new
expresión, mientras que en el segundo ejemplo:unique_ptr<double> uptr2 (pd);
El puntero se almacena en la
pd
variable.Conceptualmente, nada cambia (está construyendo un a
unique_ptr
partir de un puntero sin formato), pero el segundo enfoque es potencialmente más peligroso, ya que le permitiría, por ejemplo, hacer:unique_ptr<double> uptr2 (pd); // ... unique_ptr<double> uptr3 (pd);
Por lo tanto, tener dos punteros únicos que encapsulan efectivamente el mismo objeto (violando así la semántica de un puntero único ).
Por eso, la primera forma para crear un puntero único es mejor, cuando es posible. Tenga en cuenta que en C ++ 14 podremos hacer:
unique_ptr<int> p = make_unique<int>(42);
Lo que es más claro y seguro. Ahora con respecto a esta duda tuya:
Se supone que los punteros inteligentes modelan la propiedad del objeto y se encargan automáticamente de destruir el objeto puntiagudo cuando el último puntero (inteligente, propietario) a ese objeto queda fuera de alcance.
De esta manera, no tiene que recordar haber hecho
delete
en objetos asignados dinámicamente (el destructor del puntero inteligente lo hará por usted) ni preocuparse por si no eliminará la referencia de un puntero (colgante) a un objeto que ya ha sido destruido:{ unique_ptr<int> p = make_unique<int>(42); // Going out of scope... } // I did not leak my integer here! The destructor of unique_ptr called delete
Ahora
unique_ptr
es un puntero inteligente que modela la propiedad única, lo que significa que en cualquier momento de su programa habrá solo un puntero (propietario) al objeto puntiagudo, por esounique_ptr
no se puede copiar.Siempre que use punteros inteligentes de una manera que no rompa el contrato implícito que requieren que cumpla, tendrá la garantía de que no se filtrará memoria y se aplicará la política de propiedad adecuada para su objeto. Los punteros crudos no le dan esta garantía.
fuente
model object ownership
,integer leak
en el código oenforcing ownership policy for object
. ¿Podría sugerir temas / recursos para aprender estos conceptos?unique_ptr
, sin obtener un error:,The 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.
aunque tengo#include <utility>
y#include <memory>
. ¿Algún consejo?No hay diferencia en trabajar en ambos conceptos de asignación a unique_ptr.
int* intPtr = new int(3); unique_ptr<int> uptr (intPtr);
es parecido a
unique_ptr<int> uptr (new int(3));
Aquí unique_ptr elimina automáticamente el espacio ocupado por
uptr
.Si crea un número entero en el espacio del montón (usando nueva palabra clave o malloc ), tendrá que borrar esa memoria por su cuenta (usando delete o free respectivamente).
En el siguiente código,
int* heapInt = new int(5);//initialize int in heap memory . .//use heapInt . delete heapInt;
Aquí, tendrá que eliminar heapInt, cuando termine de usar. Si no se elimina, se produce una pérdida de memoria.
Para evitar tales fugas de memoria, se utiliza unique_ptr , donde unique_ptr elimina automáticamente el espacio ocupado por heapInt cuando sale del alcance. Por lo tanto, no es necesario eliminar o liberar para unique_ptr.
fuente
Se garantiza que los punteros únicos destruirán el objeto que administran cuando se salgan de su alcance. http://en.cppreference.com/w/cpp/memory/unique_ptr
En este caso:
unique_ptr<double> uptr2 (pd);
pd
será destruido cuandouptr2
salga de su alcance. Esto facilita la gestión de la memoria mediante la eliminación automática.El caso de
unique_ptr<int> uptr (new int(3));
no es diferente, excepto que el puntero sin formato no se asigna a ninguna variable aquí.fuente
Desde cppreference , uno de los
std::unique_ptr
constructores esexplícito unique_ptr (puntero p) noexcept;
Entonces, crear un nuevo
std::unique_ptr
es pasar un puntero a su constructor.unique_ptr<int> uptr (new int(3));
O es lo mismo que
int *int_ptr = new int(3); std::unique_ptr<int> uptr (int_ptr);
La diferencia es que no tienes que limpiar después de usarlo. Si no usa
std::unique_ptr
(puntero inteligente), tendrá que eliminarlo asídelete int_ptr;
cuando ya no lo necesite o provocará una pérdida de memoria.
fuente