2008-09-16 7 views

Répondre

12

L'utilisation la plus courante comme @aku a été signalée est de permettre à une modification d'un paramètre de pointeur d'être visible après le retour de la fonction.

#include <iostream> 

using namespace std; 

struct Foo { 
    int a; 
}; 

void CreateFoo(Foo** p) { 
    *p = new Foo(); 
    (*p)->a = 12; 
} 

int main(int argc, char* argv[]) 
{ 
    Foo* p = NULL; 
    CreateFoo(&p); 
    cout << p->a << endl; 
    delete p; 
    return 0; 
} 

Cela imprime

12 

Mais il y a plusieurs autres usages utiles comme dans l'exemple suivant pour itérer un tableau de chaînes et de les imprimer sur la sortie standard.

#include <iostream> 

using namespace std; 

int main(int argc, char* argv[]) 
{ 
    const char* words[] = { "first", "second", NULL }; 
    for (const char** p = words; *p != NULL; ++p) { 
     cout << *p << endl; 
    } 

    return 0; 
} 
7

OMI utilisation la plus courante est de passer référence à pointeur variable de

void test(int ** var) 
{ 
... 
} 

int *foo = ... 
test(&foo); 

Vous pouvez créer une matrice en dents de scie multidimensionnel en utilisant doubles pointeurs:

int ** array = new *int[2]; 
array[0] = new int[2]; 
array[1] = new int[3]; 
+0

Attention - "int ** var" n'est pas une référence à un pointeur mais un pointeur vers un pointeur. – Konrad

+0

@aku: Je pense que votre code est incorrect. La ligne devrait être int ** array = new int * [2]; – Destructor

3

Si vous passez un pointeur dans le paramètre en sortie, vous peut vouloir le passer comme Foo** et définir sa valeur comme *ppFoo = pSomeOtherFoo. Et à partir du département structures d'algorithmes et de données, vous pouvez utiliser cette double indirection pour mettre à jour les pointeurs, ce qui peut être plus rapide que d'échanger des objets réels par exemple.

1

Un exemple simple utiliserait int** foo_mat comme un tableau 2d d'entiers. Ou vous pouvez également utiliser des pointeurs vers des pointeurs - disons que vous avez un pointeur void* foo et vous avez 2 objets différents qui ont une référence avec les membres suivants: void** foo_pointer1 et void** foo_pointer2, en ayant un pointeur sur un pointeur que vous pouvez réellement vérifier si *foo_pointer1 == NULL qui indique que foo est NULL. Vous ne seriez pas capable de vérifier si foo est NULL si foo_pointer1 était un pointeur régulier. J'espère que mon explication était pas trop en désordre :)

1

Habituellement, lorsque vous passez un pointeur vers une fonction en tant que valeur de retour:

ErrorCode AllocateObject (void **object); 

où la fonction renvoie un code d'erreur succès/échec et remplissages dans le paramètre d'objet avec un pointeur vers le nouvel objet:

*object = new Object; 

Ceci est beaucoup utilisé dans la programmation COM dans Win32.

Ceci est plus une chose C à faire, en C++, vous pouvez souvent envelopper ce type de système dans une classe pour rendre le code plus lisible.

1

Carl: Votre exemple devrait être: (. Vous avez deux étoiles)

*p = x; 

:-)

+0

Oh, ouais, vous avez raison. Fixe, merci! –

5

Un scénario commun est l'endroit où vous devez passer un pointeur null à une fonction, et l'avoir initialisé dans cette fonction, et utilisé en dehors de la fonction. Sans l'indirection multplie, la fonction appelante n'aurait jamais accès à l'objet initialisé.

Tenir compte de la fonction suivante:

initialize(foo* my_foo) 
{ 
    my_foo = new Foo(); 
} 

Toute fonction qui appelle « initialisation (foo *) » auront pas accès à l'instance initialisées de Foo, beacuse le pointeur qui est passé à cette fonction est copie. (Le pointeur est juste un entier après tout, et les entiers sont passés par valeur.)

Cependant, si la fonction a été définie comme ceci:

initialize(foo** my_foo) 
{ 
    *my_foo = new Foo(); 
} 

... et il a été appelé comme ça ...

Foo* my_foo; 

initialize(&my_foo); 

... alors que l'appelant aurait accès à l'instance initialisée, via 'my_foo' - parce que c'est l'adresse du pointeur qui a été passé à 'initialiser'. Bien sûr, dans mon exemple simplifié, la fonction 'initialize' pourrait simplement renvoyer l'instance nouvellement créée via le mot-clé return, mais cela ne convient pas toujours - peut-être que la fonction doit retourner quelque chose d'autre.

+0

Vous pouvez également utiliser une référence ici (foo * &). Mais en dehors de cela, votre exemple est bon. –

1

En C, l'idiome est absolument nécessaire. Considérez le problème dans lequel vous voulez qu'une fonction ajoute une chaîne (pur C, donc un char *) à un tableau de pointeurs sur char *. Le prototype de la fonction nécessite trois niveaux d'indirection:

int AddStringToList(unsigned int *count_ptr, char ***list_ptr, const char *string_to_add); 

Nous appelons comme suit:

unsigned int the_count = 0; 
char   **the_list = NULL; 

AddStringToList(&the_count, &the_list, "The string I'm adding"); 

En C++, nous avons la possibilité d'utiliser des références à la place, ce qui donnerait une signature différente. Mais nous avons toujours besoin des deux niveaux d'indirection que vous avez demandés dans votre question initiale:

int AddStringToList(unsigned int &count_ptr, char **&list_ptr, const char *string_to_add); 
Questions connexes