2010-03-09 7 views
18

Cuando asigna una matriz usando new [], ¿por qué no puede averiguar el tamaño de esa matriz desde el puntero? Debe conocerse en tiempo de ejecución; de lo contrario, delete [] no sabría cuánta memoria liberar.¿Por qué no es posible acceder al tamaño de una nueva matriz [] 'd?

A menos que me falta algo?

+0

No es necesario que sepa un buen diseño simple: en un caso complejo, usted mismo debe ocuparse mucho de la administración. En general, hay funciones de depuración para su compilador que le indicarán, pero si lo necesita, probablemente su diseño sea incorrecto. –

+0

A menudo me he preguntado por qué nunca se ve un asignador que no conoce el tamaño, y requiere que se pase borrado. porque ¿con qué frecuencia has venido a eliminar un bloque de memoria y no has podido calcular fácilmente su tamaño? Supongo que nunca debió ser realmente beneficioso implementar un sistema con esta limitación ... – matt

+0

Probablemente impondría restricciones innecesarias a la implementación de una operación de bajo nivel. Después de todo, sí sabías cuánto pediste cuando asignaste el conjunto, por lo que no hay una necesidad apremiante del tiempo de ejecución para decírtelo. – UncleBens

Respuesta

14

En una implementación típica, el tamaño del bloque de memoria dinámica se almacena de alguna manera en el propio bloque; esto es cierto. Pero no hay una forma estándar de acceder a esta información. (Las implementaciones pueden proporcionar formas específicas de implementación para acceder a ella). Así es como está con malloc/free, así es como está con new[]/delete[].

De hecho, en una implementación típica de las asignaciones de memoria prima para new[]/delete[] llamadas son finalmente procesados ​​por alguna malloc/free -como par específico de la implementación, lo que significa que delete[] realmente no tiene que preocuparse por la cantidad de memoria desasignar: simplemente llama al interno free (o lo que sea que se llame), que se ocupa de eso.

Lo delete[] no necesita saber es sin embargo el número de elementos a destrucción en situaciones en las que el tipo de elemento de matriz tiene destructor no trivial. Y de eso se trata su pregunta: el número de elementos de la matriz, no el tamaño del bloque (estos dos no son iguales, el bloque podría ser más grande de lo que realmente se requiere para la matriz). Por esta razón, la cantidad de elementos en la matriz normalmente también se almacena dentro del bloque por new[] y luego se recupera por delete[] para realizar la destrucción adecuada del elemento de matriz. No hay formas estándar de acceder a este número tampoco.

(Esto significa que en caso general, un bloque de memoria típica asignado por new[] será independiente, almacenar simultáneamente tanto el tamaño de bloque físico en bytes y el recuento de elemento de matriz. Estos valores se almacenan por diferentes niveles de C++ mecanismo de asignación de memoria - asignador de memoria sin procesar y new[] respectivamente - y no interactúan entre sí de ninguna manera).

Sin embargo, tenga en cuenta que, por las razones anteriores, el recuento de elementos de matriz normalmente solo se almacena cuando el tipo de elemento de matriz tiene un destructor no trivial. Es decir. este conteo no siempre está presente. Esta es una de las razones por las que no es posible proporcionar una forma estándar de acceder a esos datos: tendrá que almacenarla siempre (lo que desperdicia memoria) o restringir su disponibilidad por tipo de destructor (lo cual es confuso).

Para ilustrar lo anterior, cuando se crea una matriz de int s

int *array = new int[100]; 

el tamaño de la matriz (es decir 100) es no normalmente almacenada por new[] desde delete[] no se preocupa de ello (int no tiene destructor). El tamaño físico del bloque en bytes (como, 400 bytes o más) normalmente se almacena en el bloque mediante el asignador de memoria sin procesar (y utilizado por el desglose de la memoria bruta invocado por delete[]), pero puede resultar fácilmente 420 para algunos razón específica de la implementación. Por lo tanto, este tamaño es básicamente inútil para usted, ya que no podrá derivar el tamaño de matriz original exacto de la misma.

+1

Sí, es posible que el asignador de memoria no conozca el tamaño de la matriz. Puede haber devuelto un bloque del siguiente tamaño más grande disponible y ni siquiera le importa que solo haya utilizado el 75% de eso. –

7

Es muy probable que pueda acceder, pero requerirá un conocimiento profundo de su asignador y no sería portátil. El estándar C++ no especifica cómo las implementaciones almacenan estos datos, por lo que no existe un método consistente para obtenerlo. Creo que no se especifica porque diferentes asignadores pueden desear almacenarlo de diferentes maneras para fines de eficiencia.

+0

Aún sería genial si el estándar hubiera especificado un operador 'len (...)', por lo que es posible obtener el tamaño de una matriz usando ese operador (y los autores pueden implementar ese operador len como lo deseen). .. :( – smerlin

+4

@smelin ¿No es para lo que es 'std :: vector <>'? – KitsuneYMG

5

Tiene sentido, ya que, por ejemplo, el tamaño del bloque asignado puede no ser necesariamente del mismo tamaño que el conjunto. Mientras que it is true puede new[] almacenar el número de elementos (llamando a cada elemento destructor), no tiene que hacerlo ya que no sería necesario para un destructor vacío. Tampoco hay una forma estándar (C++ FAQ Lite 1, C++ FAQ Lite 2) de implementar donde new[] almacena la longitud de la matriz ya que cada método tiene sus pros y sus contras.

En otras palabras, permite asignaciones tan rápido como sea posible al no especificar nada acerca de la implementación. (Si la implementación tiene que almacenar el tamaño de la matriz, así como el tamaño del bloque asignado cada vez, desperdicia memoria que puede que no necesite).

3

En pocas palabras, el estándar C++ no requiere soporte para esto. Es posible que si sabe lo suficiente sobre las funciones internas de su compilador, puede averiguar cómo acceder a esta información, pero generalmente se considera una mala práctica. Tenga en cuenta que puede haber una diferencia en el diseño de la memoria para las matrices asignadas en pila y las matrices asignadas en pila.

Recuerda que, básicamente, de lo que estás hablando aquí son matrices de estilo C, aunque new y delete son operadores C++, y el comportamiento se hereda de C. Si quieres una "matriz" C++ que sea de tamaño, debe utilizar el STL (por ejemplo, std :: vector, std :: deque).

+0

Sí, generalmente no uso arreglos estilo C, era solo una pregunta general, ya que (si fuera posible) guarda algo de memoria en muchos casos. –

Cuestiones relacionadas