Nella lezione precedente abbiamo introdotto l'array come struttura dati, e le relative modalità di dichiarazione statica (a stack) e dinamica (nello heap), supportate da C++.
Per quanto riguarda le modalità di inizializzazione dei singoli elementi dell'array, esistono molteplici possibilità. Il frammento seguente mostra ad esempio come inizializzare a zero un array di interi senza la necessità di assegnare il valore 0 ad ogni elemento:
// inizializzazioe a zero, equivalente a {0, 0, 0, 0, 0}
int a[5] = {0};
int* b = new int[5]{0};
Questa sintassi fa uso dell'inizializzatore a lista, rappresentato dalle parentesi graffe {}
, che abbiamo precedentemente usato per assegnare valori arbitrari ad ogni elemento. Il numero di elementi della lista può essere uguale o inferiore alla dimensione dell'array, ed in quest'ultimo caso i restanti elementi vengono inizializzati a zero per default. In C++ è anche possibile omettere il valore 0 tra le parentesi.
Se si vogliono inizializzare gli elementi con un valore diverso da zero, è possibile scandire tutti gli elementi dell'array per assegnare il valore desiderato, oppure ricorrere ad alcune funzioni di utilità dello standard che sono incluse nello header file <algorithm>
.
Ad esempio, il listato seguente assegna il valore -1 a tutti gli elementi di un array facendo ricorso ad una delle funzioni della libreria standard:
#include <iostream>
#include <algorithm>
int main()
{
int myArray[5] = {0};
std::fill_n(myArray, 5, -1);
for (int i=0; i<5; i++)
{
std::cout << "index: " << i
<< " - value: " << myArray[i] << "\n";
}
return 0;
}
Gli argomenti della funzione std::fill_n
sono il puntatore ad una delle locazioni dell'array, in questo caso la prima, il numero di elementi da inizializzare, ed il valore desiderato.
Applicando l'algebra dei puntatori è possibile restringere l'inizializzazione ad un intervallo specifico di elementi e reiterare l'invocazione di std::fill_n
per inizializzare più intervalli con i valori desiderati, come mostrato nel frammento seguente:
int myArray[5] = {0}; // {0, 0, 0, 0, 0}
std::fill_n(myArray, 2, -1); // {1, -1, 0, 0, 0}
std::fill_n(myArray + 3, 2, 1); // {1, -1, 0, 1, 1}
In alternativa, è possibile generare sequenze di valori arbitrari mediante l'uso della funzione std::generate_n
, la quale, a differenza di std::fill_n
, accetta come terzo argomento un'entità invocabile come un puntatore a funzione, un funtore o una espressione lambda, usata per calcolare il valore da assegnare ad ogni elemento.
Ad esempio, il listato seguente assegna una sequenza di numeri progressivi ad un array facendo ricorso ad un funtore appositamente definito.
#include <iostream>
#include <algorithm>
// funtore che genera una sequenza di numeri progressivi
class ProgNumGenerator
{
public:
ProgNumGenerator(int start = 0, int inc = 1)
{
n = start;
step = inc;
}
int operator()()
{
int val = n;
n = n + step;
return val;
}
protected:
int n;
int step;
};
int main()
{
int size = 21;
int myArray[size] = {0};
// assegna i numeri da -10 a -1 alla prima metà dell'array
std::generate_n(myArray, size/2, ProgNumGenerator(-size/2));
// assegna i numeri da 0 a 10 alla seconda metà dell'array
std::generate_n(myArray + size/2, size/2 + 1, ProgNumGenerator(0));
for (int i=0; i<size; i++)
{
std::cout << "index: " << i
<< " - value: " << myArray[i] << "\n";
}
return 0;
}
La funzione std::generate_n
viene invocata due volte passando, tra i vari argomenti, le istanze del funtore costruite con parametri ad hoc di modo che la sequenza prodotta come risultato finale contenga un intervallo di numeri interi centrato in zero.
Le reiterate invocazioni dell'operatore ()
delle istanze dei due funtori producono i valori da usare per l'inizializzazione degli elementi dell'array nel contesto della funzione std::generate_n
chiamante.
Utilizzando le funzioni della libreria standard di C++ come alternativa alla scansione lineare di un array, è possibile parametrizzare le istruzioni per la sua inizializzazione incrementando la riusabilità del codice, qualora tali operazioni dovessero essere applicate in più parti del nostro programma.