Pointeurs

par Tom
le 16/10/2021

Pré-préambule

La tactique "rajouter des * et des & jusqu'à ce que ça compile" est À OUBLIER DÉFINITIVEMENT, ÇA NE VOUS CAUSERA QUE DES PROBLÈMES

SI VOTRE PROGRAMME COMPILE PAS À CAUSE D'UN PROBLÈME DE CE GENRE, ALORS Y'A DES NOTIONS QUE VOUS N'AVEZ PAS COMPRISES

Si vous rajoutez au pif et que ça finit par compiler, vous avez 9 chances sur 10 pour que ça ne fasse pas vraiment ce que vous attendiez, mais comme ça compilera, vous aurez encore plus de mal qu'au départ pour voir ce qui va pas !

Préambule

Imagine que tu veux agrandir ton portefeuille immobilier, en investissant par exemple dans une SCI
Tu vas chez stéphane plaza tu dis bjr jveux une maison
Quand tu donnes ton argent
Stéphane plaza il te donne pas la maison telle quelle

Il te donne l'adresse de la maison
(et éventuellement les clés mais osef)

Mais il va pas te tendre la main avec la maison là comme ça
C'est un peu gros à transporter une maison Une maison c'est gros
Chiant à déplacer

On préfère parler en termes d'adresse

Et idem quand tu as plus besoin de ta maison et que tu veux la faire raser, Tu vas pas donner ta maison à un destructeur
Tu vas lui donner l'adresse de la maison

I - Adresses

Donc ici on a vu qu'on a un truc assez gros (une maison) dont on veut parler et qu'on veut manipuler, mais qui est chiant à déplacer et transporter car très gros
bien chiant

Cependant, on sait un truc de la maison : elle a peu de chances de bouger de là où elle est, 43 rue de la paix à marly gomont

Sachant qu'elle n'en bougera pas, et qu'il n'y a qu'une maison au 43 rue de la paix à marly gomont, et ben on peut juste tout le temps utiliser cette adresse pour parler de la maison

Ça reste une adresse : si ton pote te demande à quoi ressemble ta maison et que tu lui montres une photo d'une feuille avec ton adresse dessus, il te dira "wtf mec"

Faudra que tu prennes ton petit gps, que t'ailles à l'adresse, et seulement là tu pourras prendre une photo de la maison susmentionnée

Donc
Maintenant on passe au C

Maison demickey; // je construis ma maison, nous sommes au 43 rue de la paix à marly gomont

Imaginons que je veuille faire une fonction "prendre une photo d'une maison et envoyer à patrick"
Je pourrais faire

void prendre_photo_envoyer_patrick(Maison truc)

Sauf que du coup dès que j'appellerais la fonction faudra reconstruire la maison dans la pile de la fonction et tout bref c'est chiant

Donc à la place je vais juste donner au photographe l'adresse de la maison, 43 rue de la paix à marly gomont

Et en C un type adresse ça se note *
Et pour prendre l'adresse de la maison j'utilise l'opérateur &

void prendre_photo_envoyer_patrick(Maison* truc) { ... }

prendre_photo_envoyer_patrick(&demickey); // ici, &demickey == 43 rue de la paix à marly gomont

II - allocation dynamique

Ici, j'ai créé ma maison comme ça

Maison demickey;

Concrètement ça équivaut à dire je veux une maison puis à la construire là dans ma chambre
Un peu chiant
(on appelle ça de l'allocation statique parce que une maison déclarée comme ça sera toujours dans ma chambre)

Je préfère la construire sur un beau terrain adapté quelque part

Pour ça il me faut un terrain
Je vais donc appeler Stéphane Malloc, vendeur de terrains

Il a juste besoin de savoir quelle taille fera ma maison
en C, je connais la taille via sizeof

Et donc stéphane malloc évidemment ne me donnera pas ma maison telle quelle mais l'adresse postale du terrain

En code, ça donne

Maison* demickey = malloc(sizeof(Maison));

(on appelle ça une allocation dynamique parce qu'on sait pas où malloc ira mettre ma maison, on sait juste qu'elle sera quelque part)

Et le jour où je voudrai faire raser ma maison pour pouvoir revendre le terrain, je ferai appel à monsieur Free, qui viendra raser la maison avec son bulldozer

free(demickey);

Là encore, je lui donne pas la maison telle quelle mais son adresse postale.

Notez bien, d'ailleurs, que je ne fais que lui donner l'adresse. En soi, il n'a aucune obligation de vraiment raser la maison, de la même manière que si je vends ma maison à quelqu'un, alors cette personne peut décider d'habiter dedans ou bien de la détruire, c'est elle qui choisit.

free(...) ne signifie en fait pas vraiment "effacer" mais plutôt "rendre/revendre la mémoire à l'ordinateur".

⚠ Erreur courante : free(...) sur un truc alloué statiquement

Si j'ai

Maison demickey;

On a dit que la maison est dans ma chambre (et c'est nul car je voudrais qu'elle soit sur un beau terrain etc...)

Mais que se passe-t-il si j'essaie d'appeler free ?

free(demickey);

Ça ne compilera pas car free attend une adresse, et donc là on pourrait s'arrêter ici et se rappeler que free est censé libérer quelque chose créé avec malloc.

Mais on pourrait aussi être tenté de se dire "bon, c'est du C, il veut que ça soit un pointeur, je vais juste rajouter des & jusqu'à ce que ça compile" (réaction courante de débutant) :

free(&demickey);

Ceci vous vaudra une erreur à l'exécution, qui prendra des formes variées selon le compilateur et l'OS, mais pour reprendre l'analogie ça revient à faire venir le bulldozer dans ma chambre.

Je sais pas pour vous mais je n'aime pas quand un bulldozer vient dans ma chambre.

III - C++

Passons maintenant au C++

En C++, ils ont vu que malloc+free était un duo très populaire et les ont donc intégré direct dans le langage sous la forme des mots-clés new et delete

C'est strictement identique en fonctionnement, on passe juste de fonctions à mots-clés