HOWTO · C++
Accedi alle funzioni dei membri dal puntatore a un vettore in C++
Scopri come chiamare i membri di std::vector tramite un puntatore in C++, passare il puntatore al vettore a una funzione e iterare sui suoi elementi.
In questa pagina
Per chiamare un membro di un vettore C++ tramite un puntatore, usa ptr->member; la forma equivalente è (*ptr).member. Il puntatore deve riferirsi all’oggetto vettore stesso. Ottieni l’indirizzo dell’oggetto con &, quindi usa una delle due espressioni per membri come size() e at(). L’esempio seguente passa anche il puntatore a una funzione e legge tramite esso ciascun valore.
Usa -> per accedere a un vettore tramite un puntatore
Dichiara un puntatore scrivendo il tipo del vettore seguito da *. Per un vettore di interi, il tipo è std::vector<int>*. Se values è un vettore esistente, &values è il suo indirizzo: assegnandolo al puntatore, questo si riferisce al vettore. Il vettore non viene copiato e non viene creata una raccolta separata.
L’operatore freccia combina la dereferenziazione del puntatore con la selezione di un membro. Perciò ptr->size() chiama size() sul vettore a cui punta ptr. Puoi passare lo stesso puntatore a una funzione con un parametro dello stesso tipo. Nell’esempio completo, report_size riceve un puntatore a un vettore const perché lo legge soltanto. La qualifica const impedisce alla funzione di modificare il vettore tramite il parametro, ma non cambia il modo in cui viene passato il puntatore.
Esegui questo esempio:
#include <cstddef>
#include <iostream>
#include <vector>
void report_size(const std::vector<int>* ptr) {
std::cout << "Count: " << ptr->size() << '\n';
}
int main() {
std::vector<int> values{10, 20, 30};
const std::vector<int>* ptr = &values;
report_size(ptr);
for (std::size_t i = 0; i < ptr->size(); ++i) {
std::cout << (*ptr).at(i) << '\n';
}
}
Count: 3
10
20
30
L’esecuzione stampa la dimensione del vettore, seguita da ciascun valore su una riga separata. Il vettore è una variabile locale automatica e il puntatore viene usato solo finché il vettore rimane nell’ambito. Nel tuo programma, assicurati che un puntatore non resti in uso oltre la durata dell’oggetto di cui contiene l’indirizzo.
Usa (*ptr).member per accedere a un vettore tramite un puntatore
L’espressione (*ptr).member dereferenzia prima ptr, ottenendo l’oggetto vettore, e poi seleziona uno dei suoi membri con .. Le parentesi sono importanti: senza di esse, l’operatore punto verrebbe applicato a ptr prima della dereferenziazione, producendo un’operazione diversa da quella desiderata. Per un membro del vettore, (*ptr).size() e ptr->size() hanno lo stesso significato. La forma con la freccia è più breve; quella con dereferenziazione e punto rende esplicite entrambe le operazioni.
Nell’esempio precedente, (*ptr).at(i) accede a un elemento tramite indice dopo aver dereferenziato il puntatore al vettore. La chiamata al membro viene comunque eseguita sul vettore, mentre at(i) restituisce l’intero selezionato. Questa distinzione è utile quando leggi il codice: ptr è un puntatore a un vettore, ma (*ptr).at(i) si riferisce al valore di un elemento. Se una funzione deve operare sul vettore, passale un puntatore al vettore; se deve operare su un singolo elemento, usa invece un riferimento all’elemento o un puntatore appropriato a quell’elemento.
Itera sugli elementi tramite un puntatore a un vettore
Il ciclo usa ptr->size() come condizione di terminazione e accede a ciascun valore con (*ptr).at(i). Entrambe le operazioni passano attraverso il puntatore al vettore. Potresti scrivere la chiamata al membro indicizzato anche con la freccia, come ptr->at(i): seleziona lo stesso membro del vettore. std::size_t, incluso da <cstddef>, è un tipo senza segno adatto alla dimensione e agli indici del vettore.
Un puntatore a un vettore è diverso sia da un iteratore del vettore sia da un puntatore a un singolo elemento. Il puntatore in questo esempio si riferisce all’intero oggetto std::vector<int>. Un iteratore è una posizione fornita dal contenitore per attraversarne gli elementi, mentre un puntatore a un elemento si riferisce a uno dei valori memorizzati. Il ciclo indicizzato mantiene distinti questi ruoli ed è utile quando serve un indice. Se devi soltanto visitare ogni valore, puoi anche usare un ciclo basato sull’intervallo su *ptr, ma in quel caso iteri sul vettore senza dimostrare a ogni passaggio l’accesso ai membri tramite il puntatore.
Poiché l’esempio non modifica il vettore durante l’iterazione, l’accesso tramite indice è semplice. Se in un programma inserisci o rimuovi elementi durante l’attraversamento, riconsidera il ciclo: queste operazioni possono cambiare la dimensione del vettore e invalidare riferimenti, puntatori o iteratori ai suoi elementi. Un puntatore all’oggetto vettore continua a riferirsi a quell’oggetto, ma non rende stabili le posizioni degli elementi. Mantieni in vita il vettore per tutto il tempo in cui usi il suo puntatore e scegli una logica di iterazione che tenga conto delle modifiche effettuate dal programma.