[C++] Pointeurs est références

Carambar

Elite
Salut,

Je m'emmêle toujours les pinceaux quand il s'agit de travailler avec ces notions. Si j'ai bien compris:

* : pointeur vers adresse
& : référence

Mais que signifie:

** (pointeur sur un pointeur ?)

Et comment fait-on pour chercher le pointeur d'un élément dans un tableau ?
 

null

ose();
* -> tu demandes ce qu'il y a à l'adresse vers laquelle pointe le pointeur
& -> te donne l'adresse de l'objet

** -> tu as un pointeur qui pointe sur un autre pointeur qui pointe sur un emplacement mémoire où il y a un "int" par exemple, ça va te donner la valeur du int.
 
1er
OP
Carambar

Carambar

Elite
Ok, donc pour reformuler:

* : c'est pour avoir le contenu d'une information qui se trouve à une adresse donnée.
& : c'est pour avoir l'adresse à proprement parler.

Donc on pourrait combiner les deux ? Il faudrait que je retrouve la manière dont on intialise un pointeur...

Quant au double pointeur, ca ressemble à cela en mémoire ?

* -> [*] -> [int]
 

null

ose();
Carambar a dit:
Donc on pourrait combiner les deux ? Il faudrait que je retrouve la manière dont on intialise un pointeur...
Oui bien sûr ! Image que tu ais un tableau d'objets "MonObjet". Le tableau étant un pointeur vers des objets statiques. Si tu veux avoir l'adresse à laquelle se trouve l'objet placé à la troisième position (indice 2), tu dois accéder à l'objet par le tableau (donc via le pointeur) et puis demander l'adresse de l'objet :

MonObjet *pTableau = new MonObjet[5];

int addrObj = &(*(pTableau+2));
Carambar a dit:
Quant au double pointeur, ca ressemble à cela en mémoire ?
Pour le double pointeur, imagine un tableau contenant des pointeurs d'objets. Tu dois donc utiliser un double pointeur :

MonObjet **pTableau = new MonObjet*[5];

pTableau[0] = new MonObjet("objet 1");
pTableau[1] = new MonObjet("objet 2");
pTableau[2] = new MonObjet("objet 3");
pTableau[3] = new MonObjet("objet 3");
pTableau[4] = new MonObjet("objet 4");
A noter que l'écriture avec les [] est équivalent à "pTableau+1" par exemple.
 

ailless

Asimov, Sagan, Carlin, Hitchens
Le caractère '&' peut-être utilisé dans 2 situations.

1) Dans le cas d'un passage d'adresse à une fonction (méthode classique en C)
2) en C++, on donne l'adresse d'un attribut sans devoir le préciser lors de l'appel de la fonction, c'est ce qu'on appelle passage par référence.

Pour ta question sur **, essaye de comprendre avec les arguments du main.

Le main peut avoir 3 formes :

int main(void) : le programme ne peut recevoir aucun paramètre
int main(int argc, char **argv) ou encore int main(int argc, char *argv[]) : le programme peut recevoir des paramètres

Et une dernière qui prend l'environnement en plus.

Dans la deuxième manière, argc correspond au nombre d'argument passé au programme alors que le deuxième (argv) est un tableau de chaine de caractères comportant les paramèrtes.

Si tu n'avais que char *argv, cela aurait correspondu à un simple tableau d'objet ou de types basiques mais pas de chaines de caractères.

C'est assez difficile à expliquer donc désolé mais bon quand t'avanceras, tu comprendras peut-être mieux le principe.

#include <iostream>
#include <cstdlib>
#include <string>

using namespace std;

void foo(string*);
void foo2(string&);
void foo3(string);

int main(int argc, char **argv)
{
string x("test");

/*
* foo attend une adresse de manière explicite que tu donnes avec
* '&'
* c'est la manière de donner des paramètres par adresse en C
*/
foo(&x);

cout << "x apres foo : " << x << endl;

/*
* foo2 attend l'adresse d'un string mais ici on utilise ce qui a été instauré
* par le C++ : la référence
* tu n'as pas besoin de préciser que tu donnes l'adresse, c'est "plus simple" à utiliser
*/
foo2(x);

cout << "x apres foo2 : " << x << endl;

/*
* ici, tu donnes l'adresse par valeur donc il va y avoir une copie dans la fonction
* toute modification sur la copie n'affectera pas l'originale
*/
foo3(x);

cout << "x apres foo3 : " << x << endl;

if (argc > 1)
{
cout << endl << "Affichage des arguments reçus : " << endl;

for (int i = 0; i < argc; i++)
{
cout << i << " : " << argv << endl;
}
}

return EXIT_SUCCESS;
}

void foo(string* s)
{
*s = "foo";
}

void foo2(string& s)
{
s = "foo2";
}

void foo3(string s)
{
s = "foo3";
}


J'ai fait ce petit code d'exemple afin que tu vois bien la différence entre les 2 '&' ainsi qu'un petit exemple pour les paramètres récupérés avec le lancement du programme.

argv[0] est toujours égal au nom du programme.

Ce code nous donne :

awesome@awesome-desktop:~/Projects/test$ g++ main.cpp -Wall -o x
awesome@awesome-desktop:~/Projects/test$ ./x
x apres foo : foo
x apres foo2 : foo2
x apres foo3 : foo2
awesome@awesome-desktop:~/Projects/test$ ./x test gamerz
x apres foo : foo
x apres foo2 : foo2
x apres foo3 : foo2

Affichage des arguments reçus :
0 : ./x
1 : test
2 : gamerz
awesome@awesome-desktop:~/Projects/test$
Tu peux toujours aller voir ici : http://www.siteduzero.com/tutoriel-3-11141-nouveautes-pour-les-variables.html#ss_part_5

cela te montre les différences entre pointeurs/référence
 
Haut