que - punteros c++ pdf
¿Por qué no eliminar establecer el puntero a NULL? (12)
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, puedo pensar en algunas razones por las que el estándar hubiera restringido esto:
Actuación:
Una instrucción adicional podría ralentizar el rendimiento de
delete
.Podría ser debido a los indicadores de
const
.Entonces, de nuevo, estándar podría haber hecho algo para este caso especial, supongo.
¿Alguien sabe las razones exactas para no permitir esto?
Aquí hay otra razón; supongamos que delete establece su argumento en NULL:
int *foo = new int;
int *bar = foo;
delete foo;
¿Debería establecerse bar en NULL? ¿Puedes generalizar esto?
C ++ le permite definir su propio operador nuevo y eliminarlo para que, por ejemplo, use su propio asignador de grupo. 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.
Establecer 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.
La filosofía de C ++ es "pagar por ella 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.
Porque realmente no es necesario hacerlo, y porque sería necesario eliminar el puntero a puntero en lugar de simplemente puntero.
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 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 que se elimine . 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, hay una amplia gama de punteros inteligentes a su servicio o puede escribir uno propio, mejor y más inteligente.
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 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 idiomas estructuran sus referencias para lograr un objetivo similar de una manera diferente).
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 quieres que sea nulo, escribe null :)
Un puntero se puede guardar en más de una variable, establecer uno de ellos 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, puedes crear tu propia función que haga lo que quieras:
template<typename T>
void deleten(T *&ptr) {
delete ptr;
ptr = NULL;
}
Veo gente 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 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 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ó.
El propio Stroustrup 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 vuelto popular entre los implementadores.
Pero el problema principal que plantea es que el argumento de eliminación no necesita ser un valor.
delete
se usa principalmente en destructores, en cuyo caso establecer un miembro en NULL no tiene sentido. Unas líneas más adelante, al 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, haría que el siguiente código sea ilegal:
T* const foo = new T;
delete foo;