2010-11-19 8 views
9

Mi piacerebbe capire cosa succede quando si aumenta la dimensione di un array dinamico.Cosa succede quando si aumenta la dimensione di un array dinamico?

mia comprensione finora:

  • esistenti elementi dell'array rimarranno invariati.
  • I nuovi elementi di matrice vengono inizializzati su 0
  • Tutti gli elementi di matrice sono contigui nella memoria.

Quando la dimensione dell'array viene aumentata, la memoria aggiuntiva verrà aggiunta al blocco di memoria esistente oppure gli elementi esistenti verranno copiati in un blocco di memoria completamente nuovo?

La modifica della dimensione di un array dinamico ha conseguenze per i puntatori che fanno riferimento a elementi di array esistenti?

Grazie,

[modifica] presupposto errato depennata. (I nuovi elementi della matrice vengono inizializzati a 0)

+0

[La documentazione è stata modificata il 26 ottobre] (http://docwiki.embarcadero.com/VCL/e/index.php?title=System.SetLength&diff=414648&oldid=411229), quindi l'elemento barrato è ora corretto : "lo spazio appena assegnato è impostato su 0 o zero." –

+0

La domanda è in che versione di Delphi è stata introdotta? Il documento a cui @Rob è collegato è Delphi XE, ma posso vedere la chiamata FillChar (quella che Rob ha menzionato nel suo commento alla mia risposta) anche nella procedura DynArraySetLength di D2009 ... –

+0

Lo spazio appena allocato è stato effettivamente inizializzato a 0 o zero zero almeno da D5 in poi (è quello che potrei facilmente controllare). Vedi aggiornamento alla mia risposta. E probabilmente dall'introduzione di array dinamici come @David ha commentato la mia risposta. –

risposta

10
  • esistenti elementi dell'array rimangono invariati:
  • Nuovi elementi del campo vengono inizializzati a 0: (vedi aggiornamento) senza, salvo è un array di tipi gestiti dal compilatore come string, un altro array o una variante
  • Tutti gli elementi dell'array sono contigui nella memoria:

Quando la dimensione della matrice è aumentato , l'array sarà copiati. Dalla doc: ... la memoria per un array dinamico viene riallocata quando si assegna un valore all'array o lo si passa alla procedura SetLength.

Così , aumentando la dimensione di un array dinamico ha conseguenze per puntatori fanno riferimento a elementi di array esistenti.

Se si desidera mantenere riferimenti a elementi esistenti, utilizzare il relativo indice nell'array (a base 0).

Aggiornamento

commenti di Rob e David mi ha spinto a verificare l'inizializzazione degli array dinamici a Delphi5 (come ho fatto io che prontamente disponibili in ogni caso). Prima di tutto usare del codice per creare vari tipi di array dinamici e controllarli nel debugger. Erano tutti inizializzati correttamente, ma quello poteva ancora essere un risultato prima dell'inizializzazione della posizione di memoria in cui erano allocati. Quindi controllato la RTL. Si scopre D5 ha già la dichiarazione fillchar nel metodo DynArraySetLength che Rob ha sottolineato:

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

Grazie Marjan. Devo ripensare alla mia implementazione della doppia lista collegata. – Shannon

+0

Nelle attuali implementazioni, i nuovi elementi dell'array ** sono ** inizializzati a zero. Questo è semplicemente un dettaglio di implementazione, però; non c'è alcuna garanzia che continuerà a funzionare in questo modo, e sono abbastanza sicuro che nelle versioni precedenti, non * funzionasse in quel modo. –

+0

@Rob: l'hai trovato nella VCL/RTL? Coz interessato se la tua affermazione è basata sull'osservazione, potrebbe essere correlata alla tua macchina. Ricordo che una volta che un'app funzionava perfettamente su una macchina e si bloccava con un AV su un'altra, l'unica differenza era il processore e/o la modalità di inizializzazione della memoria da parte del sistema operativo ... –

2

In pratica Embarcadero sarà sempre zero inizializzare nuovi elementi, semplicemente perché fare altrimenti avrebbe rotto così tanto di codice.

In effetti è un peccato che non garantiscano ufficialmente l'assegnazione zero perché è così utile. Il punto è che spesso nel sito di chiamata quando si scrive SetLength non si sa se si sta crescendo o riducendo la matrice. Ma l'implementazione di SetLength lo sa - chiaramente deve farlo. Quindi ha davvero senso avere un'azione ben definita su ogni nuovo elemento.

Inoltre, se vogliono che le persone siano in grado di passare facilmente da mondi gestiti a mondi nativi, allora è desiderabile l'assegnazione a zero poiché è quello che si adatta al codice gestito.

+0

* 'In pratica l'Embarcadero azzererà sempre l'inizializzazione '* - Sai per caso se questo vale anche per Free Pascal? – Wolf

+1

Non lo faccio, dal momento che non uso Free Pascal. Ma dovrebbe essere abbastanza facile da controllare nel loro codice sorgente. Inoltre, sarei sbalordito se non facessero lo stesso con Delphi dato che sono motivati ​​a rendere più facile scrivere codice che funzioni allo stesso modo sia in Delphi che in FPC. –

+0

Grazie per il suggerimento. Quello che ho trovato nel mio 'C: \ lazarus \ fpc \ 2.6.4 \ source \ rtl \ inc \ dynarr.inc' (partendo dalla riga 137) appare così. BTW: Non è stato facile da trovare, ho dovuto produrre un errore di debugger ('SetLength (myArray, -1);') per ottenere 'SetLength' tradotto in' fpc_dynarray_setlength' ;-) – Wolf

Problemi correlati