c++ - tutorial - ¿Por qué el entorno de ejecución no puede decidir eliminar o eliminar[] en lugar del programador?
videos de logica de programacion (4)
He leído que se necesita el operador delete[]
porque el entorno de ejecución no guarda información sobre si el bloque asignado es una matriz de objetos que requieren o no llamadas destructoras, pero en realidad guarda información sobre dónde está en la memoria la asignación Bloque almacenado, y también, por supuesto, el tamaño del bloque.
Solo se necesitaría un poco más de metadatos para recordar si es necesario llamar a los destructores para eliminarlos o no, ¿por qué no hacerlo?
Estoy bastante seguro de que hay una buena explicación, no la cuestiono, solo deseo saberla.
Básicamente, todo se reduce al diseño del lenguaje, ya que no quiere poner demasiadas restricciones a los implementadores. Muchos tiempos de ejecución de C ++ usan malloc()
para ::operator new ()
y free()
(más o menos) para ::operator delete ()
. malloc
/ free
estándar no proporciona la contabilidad necesaria para registrar una cantidad de elementos y no proporciona una manera de determinar el tamaño de malloc
''d en free
tiempo free
. Agregar otro nivel de manipulación de la memoria entre el new Foo
y el malloc
para cada objeto individual es, desde el punto de vista de C / C ++, un gran salto en la complejidad / abstracción. Entre otras cosas, agregar esta sobrecarga a cada objeto arruinaría algunos enfoques de administración de memoria que están diseñados para saber cuál es el tamaño de los objetos.
C ++ le permite ser lo más eficiente posible, por lo que si tuvieran que rastrear la cantidad de elementos en un bloque, serían solo 4 bytes adicionales utilizados por bloque.
Esto podría ser útil para muchas personas, pero también evita la eficiencia total para las personas que no les importa poner [].
Es similar a la diferencia entre c ++ y Java. Java puede ser mucho más rápido de programar porque nunca tiene que preocuparse por la recolección de basura, pero C ++, si se programa correctamente, puede ser más eficiente y usar menos memoria porque no tiene que almacenar ninguna de esas variables y usted puede decidir cuándo. eliminar bloques de memoria.
Creo que la razón es que C ++ no te obliga a hacer nada que no quieras. Agregaría metadatos adicionales y, si alguien no lo usara, se les impondría esa sobrecarga adicional, en contraste con los objetivos de diseño del lenguaje C ++.
Cuando desea la capacidad que describió, C ++ proporciona una manera. Se llama std::vector
y casi siempre debería preferirlo, otro tipo de contenedor o un puntero inteligente en lugar de new
y delete
.
Hay dos cosas que necesitan ser aclaradas aquí.
Primero: el supuesto de que
malloc
mantiene el tamaño exacto que pidió.
Realmente no. malloc
solo le importa proporcionar un bloque que sea lo suficientemente grande. Aunque, por razones de eficiencia, es probable que no sea una ubicación general, aún le dará un bloque de tamaño "estándar", por ejemplo un bloque de 2^n
bytes. Por lo tanto, el tamaño real (como en, el número de objetos realmente asignados) es efectivamente desconocido.
Segundo: el "bit extra" requerido
De hecho, la información requerida para que un objeto dado sepa si es parte de una matriz o no sería simplemente un bit adicional. Lógicamente
Sin embargo, en lo que respecta a la implementación, ¿dónde pondrías ese bit?
La memoria asignada para el objeto en sí probablemente no debería tocarse, el objeto lo está utilizando después de todo. Asi que ?
- en alguna plataforma, esto podría mantenerse en el puntero en sí (algunas plataformas ignoran una parte de los bits), pero esto no es portátil
- por lo que requeriría un almacenamiento adicional, al menos un byte, excepto que con problemas de alineación podría ascender a 8 bytes.
Demostración: (no es convincente como se señala por algo, ver más abajo)
// A plain array of doubles:
+-------+-------+-------
| 0 | 1 | 2
+-------+-------+-------
// A tentative to stash our extra bit
+-------++-------++-------++
| 0 || 1 || 2 ||
+-------++-------++-------++
// A correction since we introduced alignment issues
// Note: double''s aligment is most probably its own size
+-------+-------+-------+-------+-------+-------
| 0 | bit | 1 | bit | 2 | bit
+-------+-------+-------+-------+-------+-------
Humpf!
EDITAR
Por lo tanto, en la mayoría de las plataformas (donde la dirección sí importa), deberá "extender" cada puntero y, en realidad, duplicar sus tamaños (problemas de alineación).
¿Es aceptable que todos los punteros sean dos veces más grandes solo para que puedas esconder ese bit extra? Para la mayoría de la gente, supongo que sería. Pero C ++ no está diseñado para la mayoría de las personas, está diseñado principalmente para personas que se preocupan por el rendimiento, ya sea la velocidad o la memoria, y como tal, esto no es aceptable.
Fin de edición
Entonces, ¿cuál es la respuesta correcta? La respuesta correcta es que recuperar la información que perdió el sistema de tipos es costoso. Desafortunadamente.