2014-08-27 15 views
5

Devo essere completamente stupido, dato che non riesco proprio ad ottenere questo bit: Come faccio ad aggiungere elementi a un array senza che questo venga copiato.D: Aggiunta di elementi alla matrice senza copiare

In altre parole diciamo che voglio creare una grande lista di qualcosa:

int[] arr; 

while (...) { // 1,000,000 iterations 
    ... 
    arr ~= something; 
    ... 
} 

Io non capisco quando ~= sarà solo aggiungere alla matrice, e quando si creerà una copia di esso .

Per chiarire, sto cercando una semantica come ArrayList in Java o C#, ovvero un contenitore astratto in cui posso inserire le cose e che crescerà se necessario, ma generalmente rimarrà lo stesso "oggetto" (cioè se viene passato in giro ecc.).

risposta

9

Funziona più o meno come un ArrayList funziona in quanto ha un capacity che è il numero di elementi che può crescere fino a quando non è necessario riallocare. Tuttavia, è complicato dal fatto che passare una matrice a una funzione lo taglia piuttosto che avere la stessa matrice. Se stai usando solo una variabile locale e non la assegni a qualcosa, non dovrebbe avere importanza quando si rialloca, se non per efficienza.

L'articolo che si dovrebbe leggere è questo: http://dlang.org/d-array-article.html

Penso che usa una terminologia leggermente sbagliato, dal momento che si riferisce al blocco di memoria che il runtime gestisce come la matrice dinamica piuttosto che T[] - che è quello che la specifica considera una matrice dinamica, mentre il blocco di memoria è quello che sta attualmente supportando la matrice, ma fa un gran lavoro di spiegazione di molti dettagli su come funzionano gli array in D. Quindi, dovrebbe essere abbastanza illuminante.

Inoltre, dovresti probabilmente considerare l'utilizzo di std.array.Appender se stai facendo un sacco di aggiunte. per esempio.

auto app = appender!(int[])(); 

while (...) { // 1,000,000 iterations 
    ... 
    app.put(something); 
    ... 
} 

int[] arr = app.data; 

Renderà l'aggiunta più efficiente. In generale, però, probabilmente farai meglio se crei array e poi operi su di essi piuttosto che accedervi di nuovo più tardi. Ovviamente, questo non si adatta a tutti i casi d'uso, ma se lo fai, non dovrai mai preoccuparti se una sezione si riferisce ancora alla stessa memoria di un'altra - o quella o codice in un modo che non ti affidi a due fette che si riferiscono alla stessa memoria.

Un'alternativa sarebbe utilizzare std.container.Array che è un tipo di riferimento completo (invece di un tipo di riferimento parziale come gli array din di D sono). Certamente, se vuoi passare attorno a un array, avere più sezioni di tutto ciò che si riferisce alla stessa memoria e continuare ad accedervi, dovresti probabilmente considerare l'utilizzo di Array.

+0

Quindi riepilogare per vedere se capisco: Finché l'array è una variabile locale che non viene passata in giro, o un membro della classe, o passata come 'ref', posso semplicemente trattarlo come un' ArrayList '. Per l'aggiunta di massa usare 'appender'. Per far passare un array di grandi dimensioni che è leggermente modificato a volte usa 'Array'. È più o meno corretto? –

+0

@AmirAbiri Più o meno, sì. Passando un array attorno ai risultati in array che puntano alla stessa memoria ma che non sono riferimenti tra loro, quindi se uno di essi deve riallocare, non si riferirà più alla stessa memoria degli altri. Quindi, se non lo si aggiunge dopo averlo passato in giro, passarlo in giro va bene, ma se lo sei, allora devi passarlo in giro con 'ref' o usare un'altra soluzione (come' Array'). E 'Appender' rende l'aggiunta più efficiente, quindi se stai costruendo un array tramite un sacco di accodamento (piuttosto che aggiungerlo poche volte), è meglio usarlo. –

Problemi correlati