Vorrei provare a rispondere anche a questo.
I puntatori sono simili ai riferimenti. In altre parole, non sono copie, ma piuttosto un modo per fare riferimento al valore originale.
Prima di ogni altra cosa, un posto in cui dovrete usare molto i puntatori è quando avete a che fare con hardware incorporato . Forse è necessario attivare / disattivare lo stato di un pin IO digitale. Forse stai elaborando un interrupt e devi archiviare un valore in una posizione specifica. Ottieni l'immagine. Tuttavia, se non hai a che fare direttamente con l'hardware e ti stai solo chiedendo quali tipi utilizzare, continua a leggere.
Perché usare i puntatori invece delle normali variabili? La risposta diventa più chiara quando hai a che fare con tipi complessi, come classi, strutture e array. Se dovessi usare una variabile normale, potresti finire per fare una copia (i compilatori sono abbastanza intelligenti da impedirlo in alcune situazioni e anche C ++ 11 aiuta, ma per ora staremo lontani da quella discussione).
Ora cosa succede se si desidera modificare il valore originale? Puoi usare qualcosa del genere:
MyType a; //let's ignore what MyType actually is right now.
a = modify(a);
Funzionerà bene e se non sai esattamente perché stai usando i puntatori, non dovresti usarli. Fai attenzione al motivo "sono probabilmente più veloci". Esegui i tuoi test e se sono effettivamente più veloci, quindi utilizzali.
Tuttavia, supponiamo che tu stia risolvendo un problema in cui è necessario allocare memoria. Quando si alloca memoria, è necessario deallocare. L'allocazione della memoria potrebbe non riuscire. È qui che i puntatori diventano utili: ti consentono di verificare l'esistenza dell'oggetto che hai assegnato e ti consentono di accedere all'oggetto per cui è stata allocata la memoria de-referenziando il puntatore.
MyType *p = NULL; //empty pointer
if(p)
{
//we never reach here, because the pointer points to nothing
}
//now, let's allocate some memory
p = new MyType[50000];
if(p) //if the memory was allocated, this test will pass
{
//we can do something with our allocated array
for(size_t i=0; i!=50000; i++)
{
MyType &v = *(p+i); //get a reference to the ith object
//do something with it
//...
}
delete[] p; //we're done. de-allocate the memory
}
Questa è la chiave per cui dovresti usare i puntatori - i riferimenti presuppongono che l'elemento a cui stai facendo riferimento esista già . Un puntatore no.
L'altro motivo per cui dovresti usare i puntatori (o almeno finirai per gestirli) è perché sono un tipo di dati che esisteva prima dei riferimenti. Pertanto, se finisci per usare le librerie per fare le cose che sai che sono migliori, scoprirai che molte di queste librerie usano puntatori ovunque, semplicemente per quanto tempo sono in giro (molto di questi sono stati scritti prima del C ++).
Se non hai utilizzato alcuna libreria, puoi progettare il tuo codice in modo tale da evitare i puntatori, ma dato che i puntatori sono uno dei tipi di base della lingua, più velocemente ti senti a tuo agio nell'usarli, più portatile le tue abilità in C ++ sarebbero.
Da un punto di vista della manutenibilità, dovrei anche menzionare che quando si utilizzano i puntatori, è necessario verificare la loro validità e gestire il caso quando non sono validi, oppure, supporre che siano validi e accettare il fatto che il tuo il programma si arresterà in modo anomalo o peggio QUANDO tale presupposto viene interrotto. Detto in altro modo, la tua scelta con i puntatori è quella di introdurre la complessità del codice o più sforzi di manutenzione quando qualcosa si rompe e stai cercando di rintracciare un bug che appartiene a un'intera classe di errori che i puntatori introducono, come il danneggiamento della memoria.
Quindi, se controlli tutto il tuo codice, stai lontano dai puntatori e invece usa i riferimenti, mantenendoli costanti quando puoi. Questo ti costringerà a pensare ai tempi di vita dei tuoi oggetti e finirà per mantenere il tuo codice più facile da capire.
Basta ricordare questa differenza: un riferimento è essenzialmente un puntatore valido. Un puntatore non è sempre valido.
Quindi sto dicendo che è impossibile creare un riferimento non valido? No. È del tutto possibile, perché C ++ ti consente di fare quasi tutto. È solo più difficile da fare involontariamente e rimarrai stupito da quanti bug non sono intenzionali :)