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
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);
- restituire un array allocato sull'heap:
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;
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.
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:
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::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::array<int, 10> ArrayDiDieciUni()
{
std::array<int, 10> ret;
for(size_t i=0; i<10; i++)
ret[i]=1;
return ret;
}
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.