c++ - descargar - ¿Cómo eliminar[] "saber" el tamaño de la matriz de operandos?
c++ manual (9)
Foo* set = new Foo[100];
// ...
delete [] set;
No pasas los límites de la matriz para delete[]
. Pero, ¿dónde se almacena esa información? ¿Está estandarizado?
Básicamente se dispone en memoria como:
[info] [mem que pediste ...]
Donde información es la estructura utilizada por su compilador para almacenar la cantidad de memoria asignada y qué no.
Sin embargo, esto depende de la implementación.
Cuando asigna memoria en el montón, su asignador hará un seguimiento de la cantidad de memoria que ha asignado. Esto generalmente se almacena en un segmento "principal" justo antes de la memoria que se le asigna. De esa manera, cuando es hora de liberar la memoria, el desasignador sabe exactamente cuánta memoria se debe liberar.
Debido a que la matriz a ''eliminar'' debería haberse creado con un solo uso del operador ''nuevo''. La operación ''nueva'' debería haber puesto esa información en el montón. De lo contrario, ¿cómo podrían los usos adicionales de los nuevos saber dónde termina el montón?
Este es un problema más interesante de lo que podría pensar al principio. Esta respuesta es sobre una posible implementación.
En primer lugar, mientras que en algún nivel su sistema tiene que saber cómo "liberar" el bloque de memoria, el malloc / free subyacente (que generalmente llama / delete / new [] / delete [] generalmente) no siempre recuerda exactamente cuánta memoria usted solicita, puede redondearse (por ejemplo, una vez que está por encima de 4K, a menudo se redondea al siguiente bloque de 4K).
Por lo tanto, incluso si pudiera obtener el tamaño del bloque de memoria, eso no nos dice cuántos valores hay en la nueva memoria [] ed, ya que puede ser más pequeño. Por lo tanto, tenemos que almacenar un entero extra que nos diga cuántos valores hay.
EXCEPTO, si el tipo que se está construyendo no tiene un destructor, entonces delete [] no tiene que hacer nada excepto liberar el bloque de memoria, y por lo tanto no tiene que almacenar nada.
Esto no es algo que está en la especificación, depende de la implementación.
La información no está estandarizada. Sin embargo, en las plataformas en las que he trabajado, esta información se almacena en la memoria justo antes del primer elemento. Por lo tanto, teóricamente puedes acceder a él e inspeccionarlo, pero no vale la pena.
También es por esto que debe usar delete [] cuando asignó memoria con new [], ya que la versión de array de delete sabe que (y dónde) debe buscar para liberar la cantidad correcta de memoria, y llamar al número apropiado de destructores para los objetos.
No está estandarizado. En el tiempo de ejecución de Microsoft, el nuevo operador usa malloc () y el operador de eliminación usa free (). Entonces, en esta configuración, su pregunta es equivalente a la siguiente: ¿Cómo sabe free () el tamaño del bloque?
Hay algo de contabilidad pasando detrás de las escenas, es decir, en el tiempo de ejecución de C.
Se define en el estándar de C ++ para ser específico del compilador. Lo que significa compilador de magia. Se puede romper con restricciones de alineación no triviales en al menos una plataforma principal.
Puede pensar en posibles implementaciones al darse cuenta de que delete[]
solo se define para los punteros devueltos por new[]
, que puede no ser el mismo puntero que devolvió el operator new[]
. Una implementación en el campo es almacenar el conteo de la matriz en el primer int devuelto por el operator new[]
, y hacer que el new[]
devuelva un puntero compensado más allá de eso. (Esta es la razón por la cual las alineaciones no triviales pueden romper el new[]
.)
Tenga en cuenta que el operator new[]/operator delete[]
! = new[]/delete[]
.
Además, esto es ortogonal a cómo C conoce el tamaño de la memoria asignada por malloc
.
Uno de los enfoques para los compiladores es asignar un poco más de memoria y almacenar un recuento de elementos en un elemento principal.
Ejemplo de cómo se podría hacer:
aquí
int* i = new int[4];
el compilador asignará sizeof(int)*5
bytes.
int *temp = malloc(sizeof(int)*5)
Almacenará "4" en los primeros bytes sizeof(int)
*temp = 4;
y establecer i
i = temp + 1;
Así que voy a apuntar a una matriz de 4 elementos, no 5.
Y supresión
delete[] i;
Se procesarán de la siguiente manera:
int *temp = i - 1;
int numbers_of_element = *temp; // = 4
... call destructor for numbers_of_element elements
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed
free (temp)