2012-09-27 23 views
20

¿Por qué no es posible obtener la longitud de una memoria intermedia asignada de esta manera.Encontrar el tamaño de la matriz dinámicamente asignada

AType * pArr = new AType[nVariable]; 

Cuando la misma matriz se cancela la asignación

delete [] pArr; 

el tiempo de ejecución debe saber cuánto desasignar. ¿Hay algún medio para acceder a la longitud antes de eliminar la matriz? Si no, ¿por qué no se proporciona esa API que obtendrá la longitud?

+1

Excelente pregunta +1 –

+0

La mejor manera es usar, 'std :: vector pArr (nVariable);'. Esto asigna internamente el uso de la asignación dinámica y usted tiene '.size()' siempre a mano. – iammilind

+1

[Entrada de C++ FAQ en esto.] (Http://www.parashift.com/c++faq-lite/num-elems-in-new-array.html) – jrok

Respuesta

4

¿Hay algún medio para acceder a la longitud antes de eliminar la matriz?

No. no hay manera de determinar eso.
El estándar no requiere que la implementación recuerde y proporcione los detalles del número de elementos solicitados a través del new.
La implementación puede simplemente insertar patrones de bits específicos al final de los bloques de memoria asignados en lugar de recordar el número de elementos, y puede que simplemente busque el patrón mientras libera la memoria.
En resumen, es únicamente un detalle de implementación.


En una nota lateral, hay 2 opciones para superar prácticamente este problema:

  1. Puede simple uso de un std::vector que le proporciona funciones miembro como size() o
  2. puede simplemente haz la contabilidad tú mismo.

newal menos asigna suficiente memoria todo lo que solicitó.
Ya sabe cuánta memoria ha solicitado para que pueda calcular la longitud fácilmente. Puede encontrar el tamaño de cada artículo usando sizeof.

Total memory requested/Memory required for 1 item = No of Items 
+0

¿Este downovte es porque ...? –

+3

No te recomendé, pero creo que el problema es que él pregunta por qué el estándar no proporciona eso, y dices que es así porque el estándar dice eso. Él está pidiendo un razonamiento, no para una solución de un problema concreto. – akappa

+0

@akappa: Mi respuesta establece la razón, puede haber formas efectivas/mejores en que una implementación puede realizar un seguimiento de la memoria asignada, y por lo tanto, el estándar no obliga a las implementaciones a hacerlo de una manera particular. De hecho, la respuesta incluso dice una de esas formas. Ya que usted dice que esto no es racional, por favor, infórmeme sobre ¿Cómo/por qué cree que esto no es una razón fundamental? –

5

El tiempo de ejecución SÍ sabe cuánto se asignó. Sin embargo, estos detalles son específicos del compilador por lo que no tiene una forma de plataforma cruzada para manejarlo.

Si desea que la misma funcionalidad y ser capaz de realizar un seguimiento del tamaño se puede utilizar un std :: vector de la siguiente manera:

std::vector<AType> pArr(nVariable); 

Esto tiene la ventaja añadida de utilizar RAII también.

+0

Acepto que la implementación es específica del compilador. Pero lo que detiene el estándar es pedirle a los proveedores de C++ que expongan una API como la que se muestra a continuación. size_t array_sizeof (void const * pHead); – Ram

+0

@Ram: No sé qué impide que el estándar lo solicite, ya que muchos tiempos de ejecución lo permiten. Puede haber alguna manera de implementar asignaciones para las cuales no se puede hacer y esa es la razón para no forzarlo a estar expuesto. Sin embargo, no puedo pensar en un patrón de asignación para el que no puedas hacerlo ... – Goz

+0

@Ram: Personalmente siempre uso vectores en lugar de asignación dinámica para los beneficios de RAII, semántica de copia y seguimiento de tamaño. – Goz

2

No, realmente no. Al menos no de una manera definida, independiente de la plataforma.

La mayoría de las implementaciones almacenan el tamaño de una matriz dinámicamente asignada antes de la matriz real.

+3

Realmente. Los que he visto no. –

+0

@JamesKanze MSVS seguramente sí. –

+0

Acabo de probarlo con VC10. Si hago 'new char [10]', 'size_t' inmediatamente antes del puntero devuelto contiene' 917978'. (Con g ++, contiene '17', que en realidad puede estar relacionado con la cantidad de memoria asignada, ya que las consideraciones de alineación requerirán redondear la cantidad hasta el siguiente múltiplo de 8.) –

3

El delete operador no necesita conocer el tamaño de liberar la memoria asignada, al igual que la llamada free sistema no lo hace. Esto se debe a que ese problema se deja al sistema operativo y no al sistema de tiempo de ejecución de los compiladores.

+1

No realmente, operación de eliminación y la función de biblioteca libre necesito saber estoCreo que muchas implementaciones no devuelven la memoria asignada al sistema operativo, sino que la reutilizan, e incluso si devuelven la memoria, no hay una asignación 1: 1 entre la invocación gratuita/eliminar y una llamada al sistema que devuelve memoria (esto es porque el sistema operativo por lo general no le permitirá devolver la memoria en trozos pequeños, sino multiplicados por un tamaño de página). –

+1

al menos para tipos de datos que no sean POD, el tiempo de ejecución TIENE que conocerlo, ya que debe llamar a los dtors. Para los tipos de datos POD es seguro decir que el C++ RTS puede o no saber cuánto espacio ha sido asignado, ya que el manejo de la memoria simple está fuera del estándar. – akappa

3

El tiempo de ejecución debe desasignar la misma cantidad que se asigna, y lo hace no perder de vista esto de alguna manera (por lo general de manera muy indirecta). Pero no hay manera confiable de obtener del monto asignado al número de elementos : la cantidad asignada no puede ser menor que el número de elementos por el tamaño de cada elemento, pero a menudo será más. consideraciones de alineación, por ejemplo, significa que new char[5] y new char[8] menudo destinará la misma cantidad de memoria, y hay diversas estrategias de asignación que pueden causar significativamente más memoria que se asignará que lo que es estrictamente necesario.

0

por qué no un poco de información extra de la siguiente manera:

template <typename T> class AType 
{ 
public: 

    AType(size_t s) : data(0) 
    { 
     a_size = s; 
     data = new T[s]; 
    } 
    ~AType() { 
     if (data != nullptr) 
      delete [] data; 
    } 

    size_t getSize() const 
    { 
     return a_size * sizeof(T); 
    } 

private: 
    size_t a_size; 
    T* data; 
}; 
1

No hay manera portátil en C++ para obtener el tamaño de una matriz asignada dinámicamente desde el puntero prima.

En MSVC y WIN32 puede obtener el tamaño del bloque asignado con la función _msize (void *).

ver https://msdn.microsoft.com/en-us/library/z2s077bc.aspx para más detalles.

Cuestiones relacionadas