une petite question : quelle est l'intérêt d'un double pointeur? (si possible, un exemple....)merci par avance
une petite question : quelle est l'intérêt d'un double pointeur? (si possible, un exemple....)merci par avance
si par exemple tu veux faire un tableau de pointeur vers int
tu devra faire:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 int main() { int **a=new int*[10]; }
ça a un intérêt en C pour modifier une valeur pointée
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 fonction (type ** var) { *var = new type(); } type * ma_var; fonction(&ma_var);
Envoyé par d-a-v-e
on peut pas écrire directement :
{
int *a=new int*[10];
}
...je comprends pas la subtilité (je débute!)![]()
L'opérateur new alloue de la mémoire et te retourne un pointeur sur le type demandé. Ce pointeur contient l'adresse du début de la zone mémoire allouée pourle type demandé.
Si tu demandes un int, il te renvoie un int* :Si tu demandes un int*, il te renvoie un int** :
Code : Sélectionner tout - Visualiser dans une fenêtre à part int* pi = new int;Si tu demandes un tableau de 10 int*, il te renvoie un int** pointant sur de début de la zone mémoire allouée pour ces 10 int* :
Code : Sélectionner tout - Visualiser dans une fenêtre à part int** ppi = new int*;Une utilisation classique des doubles pointeurs est une liste chaînée (exercice de programmation incontournable) 8)
Code : Sélectionner tout - Visualiser dans une fenêtre à part int** ppi_array = new int*[ 10 ];
Une manière classique de limiter les indirections (les *) est de passer par des références.
Je vois pas où est-ce qu'on a besoin de doubles pointeurs pour une liste chaînée.Une utilisation classique des doubles pointeurs est une liste chaînée (exercice de programmation incontournable)
+1Envoyé par loufoque
En paramètre, je vois ça comme un archaisme du C -- cf. la réponse de bigboomshakala?
Après, c'est un moyen type pour avoir des tableaux non nécessairement réguliers (non "rectangulaires) à deux dimensions => les fameux tableaux de pointeurs aux 150000 allocations -- dans un premier temps.
Autant dire que je les utilise rarement. Voire plus du tout en fait, maintenant que j'y pense. Du moins pas dans le code que je maintiens.
Blog|FAQ C++|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS|Bons livres sur le C++
Les MP ne sont pas une hotline. Je ne réponds à aucune question technique par le biais de ce média. Et de toutes façons, ma BAL sur dvpz est pleine...
Je suppose qu'il fait allusion a quelque chose comme:Envoyé par loufoque
ou le champs prev pointe vers le champs next du predecesseur ou bien vers la tete de liste, ce qui permet d'enlever un Node de la liste dont dont il fait partie sans connaitre celle-ci:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 struct Node { Node** prev; Node* next; };Avec l'inconvenient de ne pas pouvoir iterer en sens inverse.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 *node->prev = node->next; if (node->next != NULL) { node->next->prev = node->prev; }
Oui, de mémoire, on les utilisait dans ce genre d'exercices pour les itérateurs en insertion et en suppression.
@LH : Archaïsme du C ? Probable. Assez courant malheureusement, si j'en juge par mon expérience personnelle.![]()
...OK,
grossomodo, si je comprends bien, quand je cherche à récupérer l'adresse d'une variable, j'utilise un pointeur :
{
int *pi=&i;
}
et si je cherche à pointer sur l'adresse de *pi, il faut utiliser un double pointeur
{
int **pa=π
}
....ba, c'est tout simple alors!!![]()
> dernière question : les références, ça marche pareil?
Ben normalement c'est plutôt
Il suffit d'un pointeur vers l'élément précédent, ce qui permet en plus de faire des listes doublement chaînées (avec itération inverse)
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 template<typename T> struct Node { Node* prev; Node* next; T valeur; ~Node() { if(node->prev != NULL) node->prev->next = node->next; if(node->next != NULL) node->next->prev = node->prev; } };
Je ne vois pas l'intérêt de ta solution avec un pointeur vers le membre next du noeud précédent par rapport à celle-ci. (si ce n'est éviter un test ?)
Ton code est incomplet, il y a aussi quelque part un pointeur vers le premier element de la liste qui est a mettre a jour dans le cas ou le noeud enleve est le premier, et pour ca il faut savoir ou il se trouve. Avec un champs prev qui est un pointeur vers pointeur vers noeud, le champs prev peut contenir un pointeur vers la tete de liste ce qui resouds ce probleme.Envoyé par loufoque
Ah oui pardon, avec mon modèle il faut effectivement rajouter un pointeur vers la liste elle-même qui contient un pointeur vers le premier (et aussi le dernier dans le cas d'une liste doublement chaînée) des éléments.
Pour en revenir à la question du début, ces deux notations sont équivalentes ou faut-il mieux en utiliser une dans certaines situations ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part int **pi;
Car moi j'utilise toujours la seconde, ça permet une utilisation plus simple.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 int *pi; pi = new int*[10];
La deuxième notation ne devrait pas compiler.
C'est :
ou
Code : Sélectionner tout - Visualiser dans une fenêtre à part int* pi = new int[10];
Code : Sélectionner tout - Visualiser dans une fenêtre à part int**pi = new int*[10];
Ah oui je viens de m'apercevoir que j'ai dit n'importe quoi, toutes mes excuses.
Partager