Gli array in C++ non si passano per valore (quando lo passi ad una funzione decade in puntatore, nonostante la sintassi talvolta possa far credere il contrario). Purtroppo è così per ragioni di compatibilità con il C, il quale se non erro è fatto così per ragioni di compatibilità con il BCPL o roba del genere. Per motivi analoghi non è neanche possibile restituire un array per valore.
Le strategie usate in genere per gli array "stile-C" sono:
- farsi passare l'array di destinazione come parametro e scriverci dentro
- restituire un array allocato sull'heap:codice:void RiempiDiUni(int array[], size_t dimensioni) { for(size_t i=0; i<dimensioni; i++) array[i]=1; } // ... int vettore[10]; RiempiDiUni(vettore, 10);
Nota che devi necessariamente usare new[]/delete[] e non puoi restituire un puntatore ad un array allocato sullo stack all'interno della funzione, poiché questo cessa di esistere quando la funzione termina.codice:// Attenzione: questo codice non è exception-safe int * ArrayPienoDiUni(size_t dimensioni) { int * arr = new arr[dimensioni]; for(size_t i=0; i<dimensioni; i++) array[i]=1; return arr; } // ... int * arr = ArrayPienoDiUni(10); // ... // La responsabilità della deallocazione ricade sul chiamante delete [] arr;
Se però si ricorre all'allocazione dinamica, tanto vale semplificarsi la vita e usare direttamente un std::vector e dimenticarsi dei problemi di memory leak:
std::vector è ottimo quando il numero di elementi non è noto a compile-time, quando gli elementi sono tanti, in generale nei casi in cui conviene allocare sull'heap. D'altra parte, spesso l'uso dell'heap non è ottimale: in particolare, se le dimensioni dell'array sono note a compile-time e non sono troppo grandi. Per queste evenienze, nel nuovo standard C++ è fornita la classe template std::array<Tipo, Dimensione>, che fornisce un'ottima alternativa per questi casi:codice:std::vector<int> ArrayPienoDiUni(size_t dimensioni) { std::vector<int> ret(dimensioni, 1); return ret; // la copia dovrebbe essere elisa tramite NRVO } // ... std::vector<int> arr = ArrayPienoDiUni(10); // la memoria viene deallocata automaticamente quando arr esce dallo scope
std::array ha dimensioni fissate a compile-time mediante il secondo parametro template, non usa l'heap (a meno che non venga allocato esplicitamente con new) e ha un costruttore di copie, il che lo rende perfetto molti casi in cui std::vector è eccessivo.codice:std::array<int, 10> ArrayDiDieciUni() { std::array<int, 10> ret; for(size_t i=0; i<10; i++) ret[i]=1; return ret; }

Rispondi quotando