weak_ptr smart shared_ptr pointer example create c++ pointers reference shared-ptr

c++ - smart - unique pointer



boost:: shared_ptr question. ¿Por qué funciona esto? (3)

Al experimentar con esta pregunta , creé un ejemplo que no entiendo por completo. En particular, resalta mi malentendido de los punteros, las referencias y el boost :: shared_ptr.

int& r = *(new int(0));//gratuitous pointer leak, got to initialize it to something { boost::shared_ptr<int> sp(new int(100)); r = *sp; cout << "r=" << r << endl; } cout << "r=" << r << endl << endl; int* p; { boost::shared_ptr<int> sp(new int(100)); p = &*sp; cout << "*p=" << *p << endl; } cout << "*p=" << *p << endl;

Ejecutar este código da un resultado como este:

r=100 r=100 *p=100 *p=13

¿Por qué la referencia sobrevive a la muerte de shared_ptr pero el puntero no?

Hay un problema en las respuestas aquí en el sentido de que parece haber dos soluciones diametralmente opuestas y contradictorias y ningún consenso sobre cuál es la verdad. Me gustaría poder utilizar una referencia después de eliminar un shared_ptr, pero si no es válido, realmente necesito entender esto.

Quizás alguien pueda publicar un ejemplo simple que demuestre el comportamiento indefinido en la referencia.


En el segundo caso, tu ítem int se destruye. En el primer caso, no lo es.

En el primer caso, crea un nuevo ítem int con new en el ámbito externo. En el ámbito interno, usted crea un segundo objeto int , para el cual también crea un shared_ptr , que entonces posee el int -object. Este shared_ptr queda sin alcance cuando cierra el alcance interno, por lo que se destruye. El destructor shared_ptr también destruirá el objeto al que se refiere, porque ningún otro shared_ptr (que se creó a partir del original) se refiere a su objeto int más. Eso está todo bien Sin embargo, en el medio de ese alcance reasigna el valor de r al de *sp (100). Por lo tanto, guarde el valor de *sp , antes de que sp se destruya, en r .

Nota: ciertamente es un estilo cuestionable crear un objeto int la manera en que lo haces en la primera línea de código. Si no elimina explícitamente ese objeto int , este es un puerro de memoria. La forma de destruirlo sería delete &r que se ve realmente feo, especialmente porque el símbolo r aún se refiere al objeto int , ahora eliminado, int . NO HAGAS ESTO!

En el segundo caso, usted crea un puntero int al principio, pero no un objeto int . El alcance interno es casi el mismo que antes, excepto que esta vez no guarda el valor de su nuevo objeto int en la variable de ámbito externo ( p ), pero guarda la dirección del objeto int . Como el objeto int se destruye al final del ámbito interno (por la misma razón que anteriormente), p ya no apunta a un objeto int existente, sino a un lugar en la memoria que anteriormente tenía un objeto int . El valor que obtiene de *p no está definido: aún puede obtener 100, puede obtener cualquier otro valor e incluso puede bloquear su programa aquí (falla de segmentación) a medida que desreferencia una ubicación de memoria que ya no tiene.

Entonces, para resumir, y responder a su pregunta final:

La referencia sobrevive, porque todavía se refiere a un objeto existente. El puntero no, porque apunta a un objeto que ya no existe.


Porque r = *sp; no hace lo que crees que hace Se asigna al referente , es decir, al objeto int anónimo que creó en el montón en la línea 1. No puede volver a colocar las referencias en C ++.

Esto es lo que dice la norma sobre la evaluación de expresiones de referencia:

Si una expresión tiene inicialmente el tipo "referencia a T ", el tipo se ajusta a T antes de cualquier análisis posterior. La expresión designa el objeto o función denotada por la referencia , y la expresión es un valor l o un valor x, dependiendo de la expresión.

Como ve, no hay forma de llegar a "la referencia en sí". Simplemente no existe en C ++.

Tal vez este código lo aclare:

int a = 42; int b = 97; int&r = a; // r is just an alias (another name) for a r = b; // assigns b to a (does NOT bind r to b, that''s impossible in C++!)

Después de ejecutar la última línea, tanto a como b contienen 97, porque r = b realmente significa a = b .


p no está definido, r es una copia

int& r = *(new int(0)); { boost::shared_ptr<int> sp(new int(100)); r = *sp; // copy cout << "r=" << r << endl; } cout << "r=" << r << endl << endl; int* p; { boost::shared_ptr<int> sp(new int(100)); p = &*sp; cout << "*p=" << *p << endl; } cout << "*p=" << *p << endl; // Undefined, pointer points to deleted int