¿Por qué no elimina establecer el puntero a NULL?

127

Siempre me pregunté por qué la configuración automática del puntero a NULL después de la eliminación no es parte del estándar. Si esto se soluciona, muchos de los bloqueos debidos a un puntero no válido no ocurrirían. Pero habiendo dicho eso, puedo pensar en un par de razones por las cuales el estándar habría restringido esto:

  1. Actuación:

    Una instrucción adicional podría ralentizar el deleterendimiento.

  2. Podría ser por constpunteros.

    Entonces, de nuevo, el estándar podría haber hecho algo para este caso especial, supongo.

¿Alguien sabe las razones exactas para no permitir esto?

aJ.
fuente

Respuestas:

150

Stroustrup mismo responde. Un experto:

C ++ permite explícitamente una implementación de eliminar para poner a cero un operando lvalue, y esperaba que las implementaciones hicieran eso, pero esa idea no parece haberse popularizado entre los implementadores.

Pero el problema principal que plantea es que el argumento de eliminar no necesita ser un valor.

Dan Olson
fuente
Creo que esto podría usar alguna explicación más. Ni siquiera estoy seguro de lo que dice ... Supongo que tendré que volver más tarde cuando pueda dedicar un par de horas a investigar esto hasta que lo obtenga. O bien, podría exponer la respuesta para ayudarnos a comprender más rápidamente.
Gabriel Staples
63

Primero, establecer en nulo requeriría una variable almacenada en la memoria. Es cierto que generalmente tiene un puntero en una variable, pero a veces es posible que desee eliminar un objeto en una dirección calculada. Eso sería imposible con la eliminación "nula".

Luego viene el rendimiento. Es posible que haya escrito código de tal manera que el puntero se salga del alcance inmediatamente después de que se elimine . Llenarlo con nulo es solo una pérdida de tiempo. Y C ++ es un lenguaje con la ideología "¿no lo necesita? Entonces no tiene que pagarlo".

Si necesita seguridad, hay una amplia gama de punteros inteligentes a su servicio o puede escribir los suyos, mejores y más inteligentes.

diente filoso
fuente
44
Buen punto wrt dirección calculada, incluso si es algo que no se ve a menudo
snemarch
¿Está hablando de una ubicación nueva cuando dice que a veces es posible que desee eliminar un objeto en una dirección calculada? ???
Destructor
@PravasiMeet No, me refiero a algo comodelete (ptr + i)
Sharptooth
39

Puede tener múltiples punteros apuntando a esa memoria. Crearía una falsa sensación de seguridad si el puntero que especificó para la eliminación se estableció en nulo, pero no todos los demás punteros. Un puntero no es más que una dirección, un número. También podría ser un int con una operación de desreferenciación. Mi punto es que también tendría que escanear cada puntero para encontrar aquellos que hacen referencia a la misma memoria que acaba de eliminar, y anularlos también. Sería computacionalmente intenso escanear todos los punteros para esa dirección y anularlos, porque el lenguaje no está diseñado para eso. (Aunque algunos otros idiomas estructuran sus referencias para lograr un objetivo similar de una manera diferente).

AaronLS
fuente
19

Un puntero se puede guardar en más de una variable, establecer uno de estos en NULL aún dejaría punteros inválidos en las otras variables. Entonces, en realidad no ganas mucho, es más probable que estés creando una falsa sensación de seguridad.

Además de eso, puedes crear tu propia función que haga lo que quieras:

template<typename T>
void deleten(T *&ptr) {
  delete ptr;
  ptr = NULL;
}
algo
fuente
12

Porque no hay realmente ninguna necesidad de hacerlo, y porque requeriría eliminar tomar puntero a puntero en lugar de solo puntero.

snemarch
fuente
cierto, pero eso resultaría en la misma sobrecarga
snemarch
7

deletese usa principalmente en destructores, en cuyo caso establecer un miembro en NULL no tiene sentido. Unas líneas más tarde, al cierre }, el miembro ya no existe. En los operadores de asignación, una eliminación suele ir seguida de una asignación de todos modos.

Además, haría que el siguiente código sea ilegal:

T* const foo = new T;
delete foo;
MSalters
fuente
6

Aquí hay otra razón; supongamos que delete establece su argumento en NULL:

int *foo = new int;
int *bar = foo;
delete foo;

¿Debe la barra establecerse en NULL? ¿Puedes generalizar esto?

SingleNegationElimination
fuente
5

Si tiene una matriz de punteros y su segunda acción es eliminar la matriz vacía, entonces no tiene sentido establecer cada valor como nulo cuando la memoria está a punto de liberarse. Si quieres que sea nulo ... escríbelo :)

Cuenta muerta
fuente
4

C ++ le permite definir su propio operador nuevo y eliminar para que, por ejemplo, usen su propio asignador de grupo. Si hace esto, entonces es posible usar new y delete con cosas que no son estrictamente direcciones pero dicen índices en la matriz de su grupo. En este contexto, el valor de NULL (0) podría tener un significado legal (que se refiere al primer elemento del grupo).
Por lo tanto, tener Delete set NULL automáticamente en su argumento no siempre tiene el significado de: establecer el valor en un valor no válido. El valor no válido no siempre puede ser NULL.

shoosh
fuente
4

La filosofía de C ++ es "paga solo si la usas". Creo que puede responder a tu pregunta.

Además, a veces puede tener su propio montón que recuperará la memoria eliminada ... o, a veces, el puntero no es propiedad de ninguna variable. O puntero almacenado en pocas variables: es posible que cero solo una de ellas.
Como puede ver, tiene muchos problemas y posibles problemas.

bayda
fuente
3

Establecer el puntero en NULL automáticamente no resolvería la mayoría de los problemas con un mal uso del puntero. El único bloqueo que evitaría es si intenta eliminarlo dos veces. ¿Qué sucede si llama a una función miembro en dicho puntero? Todavía se bloquearía (suponiendo que acceda a las variables miembro). C ++ no le impide llamar a ninguna función en punteros NULL, ni debería hacerlo desde el punto de vista del rendimiento.


fuente
-1

Veo personas que dan respuestas extrañas a esta pregunta.

ptr = NULL; ¿Cómo puede una declaración tan simple causar un retraso en el rendimiento?

Otra respuesta es decir que podemos tener múltiples punteros apuntando a la misma ubicación de memoria. Seguramente podemos. En este caso, la operación de eliminación en un puntero haría que ese puntero sea NULL (si eliminar hace que el puntero sea NULL) y el otro puntero no sea NULL y apunte a la ubicación de memoria que está libre.

La solución para esto debería haber sido que el usuario debería eliminar todos los punteros que apuntan a la misma ubicación. Internamente debe verificar si la memoria ya está liberada que no liberar. Solo haga que el puntero sea NULL.

Stroustrup podría haber diseñado eliminar para trabajar de esta manera. Pensó que los programadores se encargarían de esto. Entonces lo ignoró.

Nimesh Bapodra
fuente