2009-03-13 19 views
30

Ho visto qualche codice, così come alcuni errori generati dal mio compilatore che hanno un token '**' prima della variabile (ad esempio ** variablename senza riferimento-- o qualcosa del genere, non riesco a ricordare esattamente a mano libera). Sono abbastanza sicuro che questo è legato ai puntatori, se dovessi indovinare sembra che stia tentando di dereferenziare due volte. '**' è abbastanza ingooglibile. Qualcuno può indicarmi un buon sito web/documentazione o qualcuno dovrebbe preoccuparsi di spiegarlo qui?Cosa è ** in C++?

Grazie.

Grandi risposte. Se posso aggiungere, quali sarebbero alcune situazioni in cui è utile avere un puntatore a un puntatore? Non dovresti semplicemente usare il puntatore originale invece di creare un altro puntatore al puntatore originale?

+1

Duplicato: http://stackoverflow.com/questions/604099/what-is-double-star –

risposta

41

** non è in realtà solo puntatore al puntatore (come nella dichiarazione), ma è anche il dereferenziamento di una dereferenziazione (in un'istruzione).

Viene utilizzato spesso in C che non ha la notazione & per i riferimenti, ad es. per aggiornare un valore di ritorno che è un tipo di puntatore:

int alloc_foo(struct foo **foo_ret) 
{ 
    *foo_ret = malloc(sizeof(struct foo)); 
    return 1; /* to indicate success; return value in foo_ret */ 
} 
7

** è un puntatore a un puntatore.

Potrebbe essere una matrice (un array di array) o un array di stringhe (un array di caratteri), ecc

9

Non è un segno **. È semplicemente un token * seguito da un altro token *. Nel tuo caso, hai un puntatore a un puntatore, ed è sottoposto a dereferenziazione due volte per ottenere ciò che viene realmente indicato.

1

Un uso comune è che permette una funzione per impostare il puntatore nullo.
Così libero (puntatore) libera la memoria allocata al puntatore ma lascia il puntatore pericolosamente puntato verso la memoria libera.
Dichiarare invece my_free (** puntatore) e chiamare my_free (puntatore &) in modo che my_free() possa impostare il puntatore su null dopo averlo liberato.

6

È un doppio dereferenziamento.

int i = 3; 
int* ptr_to_i = &i; 
int** ptr_to_ptr_to_i = &ptr_to_i; 

std::cout << **ptr_to_ptr_to_i << std::endl; 

Stampe 3.

4

Volevo solo sottolineare alcuni degli usi per un puntatore a un puntatore. La maggior parte di questi sono toccati da altri post, ma ho pensato che la reiterazione potrebbe aiutare.

  • permette una callee a modificare un puntatore di proprietà del chiamante. Ad esempio, si potrebbe passare un puntatore a un puntatore all'inizio di una stringa e il callee potrebbe modificare il puntatore puntato per puntare ora a una posizione all'interno della stringa in cui si verifica un determinato carattere.

  • Perché array degradano ai puntatori (e puntatori possono essere trattati come array), vedrete spesso un puntatore a un puntatore se si dispone di:

    • Un puntatore a un array. Questa è una generalizzazione del caso precedente, dal momento che una "stringa" (una stringa in stile C, comunque) è in realtà solo una matrice di char s.

    • Un array di puntatori. Ad esempio, potresti disporre di una serie di puntatori agli oggetti, che consentono il polimorfismo o una serie di puntatori per selezionare gli oggetti archiviati in un'altra raccolta.

    • Un array di array. Di nuovo, gli array si degradano a puntatori, quindi questo è un caso specifico di quanto sopra. Questo è spesso usato per i cosiddetti array "frastagliati" (anziché rettangolari).

22

Si può riconoscere la firma per main():

int main(int argc, char* argv[]) 

Il seguente è equivalente:

int main(int argc, char** argv) 

In questo caso, argv è un puntatore a una matrice di char *.

In C, l'operatore indice [] è solo un altro modo di eseguire l'aritmetica del puntatore. Ad esempio,

foo[i] 

produce lo stesso codice

*(foo + i) 
3
  • int **var dichiara un puntatore a un puntatore
  • **var riferimenti il ​​contenuto di un puntatore, che di per sé indica un puntatore
0

È uno dei richiami dei Sigilli C++. Dalla mia esperienza personale, posso garantire prestazioni di lettura-accesso più veloci ed efficienti utilizzando gli operatori di dereferenziazione sui vettori di STL &. Ho anche adottato metodi abituali di puntatori condivisi, se sei curioso. :)