Un assaggio di STL con i vettori

“Nell’insegnamento non si può vedere il frutto di una giornata di lavoro. È invisibile e rimane così, forse per venti anni.”
Jacques Barzun

Si dice che i programmatori siano pigri. Di sicuro, se qualcuno ha già lavorato per noi, non si vede il motivo per rifare lo stesso lavoro una seconda volta. Uno di questi “qualcuno”, nel contesto del C++, si chiama Alexander Stepanov, il quale è il principale artefice di una specifica libreria di strumenti realizzata appositamente nella visione della programmazione generica: la Standard Template Library, meglio conosciuta con l’acronimo di STL.

Alexander Stepanov
Alexander Alexandrovich Stepanov, il principale artefice della Libreria STL.

 

Volendo schematizzare al massimo la libreria STL possiamo vederla come composta di tre elementi:

Contenitori
Iteratori
Algoritmi

I contenitori, detti anche in modalità anglosassone containers, sono i veri e propri aggregati di dati. Si tratta quindi di collezioni organizzate di elementi. A scopo di esempio pensate alla struttura dati coda.
Gli iteratori sono degli speciali puntatori che consentono di navigare, cioè di muoversi, all’interno delle strutture dati.
Gli algoritmi sono delle procedure preconfezionate per risolvere i classici problemi che si presentano in relazione alle strutture dati: ordinamento di dati, ricerca di specifici valori, ecc.
Per cercare di essere minimamente concreti di seguito vi propongo un codice minimale relativo all’uso dei vettori. Sebbene il termine vettore venga spesso considerato come sinonimo di array, un vettore (vector) è una struttura dati di tipo parametrico che può essere lavorata in maniera dinamica in quanto, contrariamente ad un array che viene gestito nell’area di memoria stack, esso vive nella sezione di memoria heap.

 

#include <vector>
using namespace std; //oppure devi usare istruzioni del tipo std::vector<int> v;

int main(int argc, char** argv)
{
   printf("I vettori (vectors) non sono array ;)\n\n");
   //Dichiaro un vector (le parentesi angolari sono giustificate dal fatto che si tratta di una classe template)
   //Un vector consente la gestione di memoria contigua permettendo di riferirsi ad essa in un modo del tipo: v[0], v[1]...
   //creiamo un vector per 10 interi (vengono inizializzati a 0)

   int n = 10;

   vector<int> array(n);

   //verifichiamo il suo contenuto
   printf("Vector inizializzato:\n");
   for(int i=0; i<n; i++)
   {
      printf("%d ", array[i]);
   }
   printf("\n\n");

   // valorizziamo il vector con interi da 1 a 10
   int x =1;
   for(int i=0; i<n; i++)
   {
      array[i] = x++;
   }

   //verifichiamo il suo contenuto
   printf("Vector valorizzato con interi da 1 a 10:\n");
   for(int i=0; i<n; i++)
   {
      printf("%d ", array[i]);
   }
   printf("\n\n");

   //inserisco alla fine dell'array un nuovo elemento intero con valore 66
   array.push_back(66);

   //verifichiamo il suo contenuto
   //Usiamo ora la il metodo size() per determinare la nuova dimensione del vector
   printf("Contenuto vector dopo inserimento di un elemento in coda:\n");
   for(int i=0; i<array.size(); i++)
   {
      printf("%d ", array[i]);
   }
   printf("\n\n");

   //ora voglio ridimensionare il vector eliminando così il valore inserito
   //determino quindi l'attuale dimensione del vector
   int temp=array.size();

   //ridimensiono il vector alla dimensione attuale meno 1
   array.resize(temp-1);

   //verifichiamo il contenuto del vettore
   printf("Vector dopo il resize:\n");
   for(int i=0; i<array.size(); i++)
   {
      printf("%d ", array[i]);
   }
   printf("\n\n");

   //Un altro modo per eliminare l'ultimo elemento del vettore
   array.pop_back();
   printf("Vector dopo eliminazione elemento in coda:\n");
   for(int i=0; i<array.size(); i++)
   {
      printf("%d ", array[i]);
   }
   printf("\n");

   return 0;
}


Di seguito l’output del codice in questione:

 

Ovviamente, si tratta di un codice del tutto minimale che ha il solo scopo di far comprendere le potenzialità dei vettori del C++. Nello specifico, dichiariamo innanzitutto il nostro vector affinché contenga 10 elementi interi

int n = 10;
vector<int> array(n);

La prima cosa degna di interesse da notare è poi data dal fatto che inseriamo in coda all’array, in manoera assolutamente dinamica, un nuovo elemento, usando la seguente sintassi.

 

array.push_back(66);

 

Faccio notare, incidentalmente, la classica notazione in stile programmazione orientata agli oggetti dove push_back è il metodo dell’oggetto array.

Ancora di grande interesse è l’effettuazione del ridimensionamento del vettore con l’istruzione resize.

Infine, vi mostro come sia possibile effettuare una sorta di nuovo ridimensionamento dell’array buttando via l’ultimo elemento con l’istruzione:

 

array.pop_back();

 

Ovviamente, come detto, il precedente è un esempio assolutamente minimale che vuole solo sollecitare alla scoperta di modalità differenti per la gestione delle strutture dati.

 

Carlo A. Mazzone

Supportaci condividendo sui social il nostro articolo!