2010-11-19 10 views
9

Me gustaría entender qué sucede cuando se aumenta el tamaño de una matriz dinámica.¿Qué ocurre al aumentar el tamaño de una matriz dinámica?

Mi entendimiento hasta el momento:

  • elementos de la matriz existentes permanecerán sin cambios.
  • Los nuevos elementos de la matriz se inicializan en 0
  • Todos los elementos de la matriz están contiguos en la memoria.

Cuando se aumenta el tamaño de la matriz, ¿se insertará la memoria adicional en el bloque de memoria existente o se copiarán los elementos existentes en un bloque de memoria completamente nuevo?

¿Cambiar el tamaño de una matriz dinámica tiene consecuencias para los punteros que hacen referencia a los elementos de matriz existentes?

Gracias,

[editar] suposición incorrecta ponchó. (Elementos de nueva matriz se inicializan a 0)

+0

[La documentación cambió el 26 de octubre] (http://docwiki.embarcadero.com/VCL/e/index.php?title=System.SetLength&diff=414648&oldid=411229), por lo que su elemento tachado ahora es correcto : "el espacio recientemente asignado se establece en 0 o nulo". –

+0

La pregunta es en qué versión de Delphi se presentó esto? El documento al que @Rob vinculado es para Delphi XE, pero puedo ver la llamada de FillChar (la que Rob mencionó en su comentario a mi respuesta) en el procedimiento DynArraySetLength de D2009 también ... –

+0

El espacio recientemente asignado se ha inicializado a 0 o cero cero al menos desde D5 en adelante (eso es lo que podría verificar fácilmente). Ver la actualización de mi respuesta. Y probablemente desde la introducción de arreglos dinámicos como @David comente mi respuesta. –

Respuesta

10
  • elementos de la matriz existentes permanecerán sin cambios:
  • nuevos elementos de la matriz se inicializan a 0: (ver Boletín) sin, a menos es una matriz de tipos administrados por el compilador, como una cadena, otra matriz o una variante
  • Todos los elementos de la matriz son contiguos en la memoria:

Cuando el tamaño de la matriz es aumentó, la matriz será copiado. Desde el documento: ... la memoria de una matriz dinámica se reasigna cuando asigna un valor a la matriz o la pasa al procedimiento SetLength.

Así , aumentando el tamaño de una matriz dinámica tiene consecuencias para punteros hacen referencia a elementos de la matriz existentes.

Si desea mantener referencias a los elementos existentes, utilice su índice en la matriz (basada en 0).

actualización

los comentarios de Rob y David me impulsó para comprobar la inicialización de matrices dinámicas en Delphi5 (ya que tengo que fácilmente disponible de todos modos). Primero use algún código para crear varios tipos de matrices dinámicas e inspeccionarlas en el depurador. Todos se inicializaron correctamente, pero eso podría haber sido un resultado previo a la inicialización de la ubicación de la memoria donde se asignaron. Entonces revisé el RTL. Resulta D5 ya cuenta con la declaración FillChar en el método DynArraySetLength que Rob señaló:

// Set the new memory to all zero bits 
    FillChar((PChar(p) + elSize * oldLength)^, elSize * (newLength - oldLength), 0); 
+0

Gracias Marjan. Necesito repensar mi implementación de doble lista enlazada. – Shannon

+0

En las implementaciones actuales, los nuevos elementos ** de matriz se inicializan a cero. Sin embargo, eso es simplemente un detalle de implementación; no hay garantía de que continúe funcionando de esa manera, y estoy bastante seguro de que en versiones anteriores, * no * funcionó de esa manera. –

+0

@Rob: ¿lo encontraste en el VCL/RTL? Interesado porque si su declaración se basa en la observación, podría estar relacionada con su máquina. Recuerdo que una vez que una aplicación funcionaba bien en una máquina y se bloqueaba con una AV en otra, la única diferencia era el procesador y/o la manera en que el sistema operativo inicializaba la memoria ... –

2

En la práctica Embarcadero será siempre cero inicializar nuevos elementos simplemente porque hacer lo contrario se rompería mucho código.

De hecho, es una pena que oficialmente no garanticen la asignación de cero porque es muy útil. El punto es que a menudo en el sitio de llamadas al escribir SetLength no se sabe si está creciendo o reduciendo la matriz. Pero la implementación de SetLength sí lo sabe, claramente tiene que ser así. Entonces realmente tiene sentido tener una acción bien definida sobre cualquier elemento nuevo.

Además, si quieren que las personas puedan cambiar fácilmente entre mundos administrados y nativos, entonces la asignación de cero es deseable ya que eso es lo que se ajusta con el código administrado.

+0

* 'En la práctica, Embarcadero siempre inicializará cero * * - ¿Sabes por casualidad si esto también es cierto para Free Pascal? – Wolf

+1

No lo hago, ya que no uso Free Pascal. Pero debería ser fácil verificar su código fuente. Es más, me sorprendería si no hicieran lo mismo que Delphi, ya que están motivados para que sea más fácil escribir código que funcione igual en Delphi y en FPC. –

+0

Gracias por la pista. Lo que he encontrado en mi 'C: \ lazarus \ fpc \ 2.6.4 \ source \ rtl \ inc \ dynarr.inc' (comenzando en la línea 137) se ve así. Por cierto: No fue fácil de encontrar, tuve que producir un error de depuración ('SetLength (myArray, -1);') para obtener 'SetLength' traducido a' fpc_dynarray_setlength' ;-) – Wolf

Cuestiones relacionadas