vectores punteros puntero matriz ejemplos definicion declarar como arreglos apuntadores c++ pointers delete-operator

punteros - ¿Se garantiza que el puntero conserve su valor después de `delete` en C++?



punteros y arreglos en c (7)

Inspirado por esta pregunta .

Supongamos que en el código C ++ tengo un puntero válido y lo elimino correctamente. De acuerdo con el estándar de C ++, el puntero dejará de ser válido (3.7.3.2/4: la función de desasignación dejará inválidos todos los punteros que se refieran a todas las partes del almacenamiento desasignado ).

Al menos en la mayoría de las implementaciones, conserva el valor y almacenará exactamente la misma dirección que antes de delete , sin embargo, usar el valor es un comportamiento indefinido .

¿El estándar garantiza que el puntero mantendrá su valor o se permite que el valor cambie?


¡Esta pregunta es importante! He visto que Visual Studio 2017 ha cambiado el valor del puntero después de "eliminar". Causó un problema porque tengo que usar la herramienta de seguimiento de memoria. La herramienta estaba recopilando punteros después de cada operador "nuevo" y los comprobaba después de "eliminar". Pseudo código:

Data* New(const size_t count) { Data* const ptr(new Data[count]); #ifdef TEST_MODE DebugMemory.Collect(ptr); #endif return ptr; } void Delete(Data* const ptr) { delete[] ptr; #ifdef TEST_MODE DebugMemory.Test(ptr); #endif }

Este código funciona bien en Visual Studio 2008, pero estaba fallando en Visual Studio 2017, así que he cambiado el orden de las operaciones en la segunda función.

Sin embargo la pregunta es buena y el problema existe. Los ingenieros experimentados deben ser conscientes de eso.


Considere, ¿cómo marcaría o confiaría en cualquier respuesta de "sí" o "no"? Usted no puede O puede hacerlo, pero el resultado de esa comprobación (excepto para nullpointer) es un comportamiento indefinido.

No puede verificar un valor que no sea nulo después de una delete , por lo que la pregunta en general no tiene sentido .

Además, el argumento para delete puede ser una expresión rvalue, por lo que la pregunta no tiene sentido.

Salud y salud,


Creo que la mayoría de las implementaciones mantendrán el valor, solo por no tener ninguna razón para cambiarlo. Pero independientemente de si se mantiene el valor, sigue siendo un indicador inútil, ¿no es así?


La firma del operador global se borra, como lo exige la norma 3.7.3.2/2:

Cada función de desasignación devolverá nulo y su primer parámetro será nulo *.

Esto significa que eliminar no puede modificar el puntero que se le pasa, y siempre conservará su valor.


No se garantiza que un puntero tenga un valor significativo en sí mismo que no sea el rango en el que fue asignado y uno más allá del final de ese rango.

Lo que podría estar cuestionando es si, por ejemplo, estaba haciendo su propia comprobación de fugas, por lo que escribió la función para eliminar un puntero de un mapa después de haber eliminado. Eso usaría std :: less, que está garantizado para trabajar con punteros que no apuntan dentro de un rango, y presumiblemente funcionaría también con punteros que apuntan a una memoria que ya no es válida.

Por supuesto, puede hacer que su recolección de basura haga la "eliminación" justo antes de eliminar la memoria a la que estaba apuntando.

Como sucede con el estándar, si el valor que pasa a eliminar no es un valor l, se garantiza que mantendrá el mismo valor, pero si es un valor l se define como implementación.


No, no está garantizado y una implementación puede asignar legítimamente cero a un operando de lvalor para delete .

Bjarne Stroustrup había esperado que las implementaciones eligieran hacer esto, pero no muchas lo hacen.

http://www.stroustrup.com/bs_faq2.html#delete-zero


Si, por alguna razón, desea asegurarse de que la variable del puntero no se modifique con la delete , escriba:

delete p + 0;