2009-04-01 22 views
108

Siempre me pregunté por qué la configuración automática del puntero a NULL después de eliminar no es parte del estándar. Si esto se soluciona, muchos de los fallos debido a un puntero no válido no ocurrirían. Pero una vez dicho esto se me ocurre par de razones por las cuales la norma habría restringido el siguiente:¿Por qué no eliminar establecer el puntero a NULL?

  1. Rendimiento:

    Una instrucción adicional podría ralentizar el rendimiento delete.

  2. Podría ser por const punteros.

    Por otra parte, el estándar podría haber hecho algo para este caso especial, supongo.

¿Alguien sabe razones exactas para no permitir esto?

Respuesta

138

Stroustrup himself answers. Un extracto:

C++ permite explícitamente un ejecución de borrado a cero fuera de un operando lvalue, y yo tenía la esperanza que las implementaciones harían eso, pero esa idea no parecen tener hecho populares entre los implementadores.

Pero el problema principal que plantea es que el argumento de eliminación no necesita ser un valor l.

12

Porque no hay realmente ninguna necesidad de hacerlo, y porque sería necesario eliminar el puntero a puntero en lugar de puntero.

+1

O referencia al puntero. –

+0

cierto, pero eso daría como resultado la misma sobrecarga – snemarch

5

Si tiene una matriz de punteros, y su segunda acción es eliminar la matriz vacía, entonces no tiene sentido establecer que cada valor sea nulo cuando la memoria esté a punto de liberarse. Si quiere que sea nulo, escriba null en él :)

54

En primer lugar, establecer en nulo requeriría una variable almacenada en la memoria. Es cierto, que generalmente tiene un puntero en una variable, pero a veces puede querer eliminar un objeto en una dirección recién calculada. Eso sería imposible con "anular" eliminar.

Luego viene el rendimiento. Es posible que haya escrito el código de tal manera que el puntero saldrá del alcance inmediatamente después de borrar hecho. Llenarlo con nulo es solo una pérdida de tiempo. Y C++ es un lenguaje con la ideología de "no lo necesito, entonces no tiene que pagar por ello".

Si necesita seguridad, tiene a su disposición una amplia gama de punteros inteligentes o puede escribir uno propio, mejor y más inteligente.

+4

Buen punto wrt dirección calculada, incluso si es algo que no se ve a menudo – snemarch

+0

¿está hablando de la ubicación nueva cuando dice que a veces es posible que desee eliminar un objeto de manera justa? dirección calculada. ??? – Destructor

+0

@PravasiMeet No, me refiero a algo como 'eliminar (ptr + i)' – sharptooth

35

Puede tener varios 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 el resto de los punteros no lo hizo. 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 desreferencia. Mi punto es que también debería escanear todos los punteros para encontrar aquellos que están haciendo 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 lenguajes estructuran sus referencias para lograr un objetivo similar de una manera diferente)

17

Un puntero se puede guardar en más de una variable, establecer uno de estos en NULL aún dejará punteros no válidos en las otras variables. Entonces, realmente no gana mucho, es más probable que cree una falsa sensación de seguridad.

Además de eso, usted puede crear su propia función que hace lo que quiere:

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

C++ permite definir su propio operador de nuevo y borrar de manera que, por ejemplo, que usarían su propia piscina asignador. Si hace esto, entonces es posible usar new y delete con cosas que no son estrictamente direcciones, pero digamos índices en su conjunto de conjuntos. En este contexto, el valor de NULL (0) podría tener un significado legal (refiriéndose al primer elemento del grupo).
Así que tener eliminar establecer NULL automáticamente a su argumento no siempre tiene el significado de - establecer el valor a un valor no válido. El valor no válido puede no ser siempre NULO.

3

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

4

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

También 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 algunas variables; es posible que sea cero solo uno de ellos.
Como puede ver, tiene muchos problemas y posibles problemas.

7

delete se usa principalmente en destructores, en cuyo caso establecer un miembro en NULL no tiene sentido. Unas líneas más adelante, en el cierre }, el miembro ya no existe. En los operadores de asignación, una eliminación generalmente es seguida por una asignación de todos modos.

Además, sería hacer que el siguiente código ilegal:

T* const foo = new T; 
delete foo; 
4

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

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

¿Debería la barra establecerse en NULO? ¿Puedes generalizar esto?

-2

Veo personas dando respuestas raras 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 varios punteros apuntando a la misma ubicación de memoria . Seguramente podemos.En este caso, la operación de eliminación en un puntero solo haría que el puntero NULL (si delete estuviera haciendo el puntero NULL) y que el otro puntero no fuera NULL y apuntara a la ubicación de la memoria que es libre.

La solución para esto debería ser que el usuario elimine todos los punteros que apuntan a la misma ubicación. Internamente debería verificar si la memoria ya está liberada y no libre. Solo haz que el puntero sea NULO.

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

Cuestiones relacionadas