Résumé – Chap 2 – La copie des objets
Ce chapitre a pour objectif d’expliquer comment la mémoire est organisée et comment un programme C++ peut réserver puis libérer de la mémoire pendant son exécution.
Il commence par rappeler que toute variable possède une taille et une adresse. L’opérateur sizeof mesure l’espace occupé, tandis que l’opérateur & permet d’observer l’emplacement de la variable.
L’étude des adresses montre que la disposition des données dépend de leur taille, de leur ordre et des contraintes d’alignement imposées par la machine et le compilateur.
Le chapitre rappelle également qu’un pointeur est lui-même une variable. Il possède sa propre adresse et contient comme valeur l’adresse d’un autre objet.
Les variables locales ont généralement une durée de vie automatique liée au bloc ou à l’appel de fonction qui les contient. Leur mémoire est gérée par la pile et récupérée automatiquement lorsque leur portée se termine.
Cette gestion ne convient toutefois pas à toutes les situations. La quantité de mémoire nécessaire peut être inconnue lors de la compilation ou les données peuvent devoir survivre au bloc dans lequel elles ont été créées.
Le tas permet alors d’obtenir de la mémoire dynamiquement. L’opérateur new crée un objet pendant l’exécution et retourne son adresse, qui doit être conservée dans un pointeur.
Lorsque l’objet n’est plus nécessaire, l’opérateur delete libère sa mémoire. La destruction de l’objet ne détruit cependant pas le pointeur qui contenait son adresse.
Après la libération, ce pointeur conserve une adresse devenue invalide et devient un pointeur pendant. L’affectation nullptr permet d’indiquer explicitement qu’il ne désigne plus aucun objet.
Le chapitre étend ensuite ce mécanisme aux tableaux dynamiques. L’écriture new Type[n] réserve une zone contiguë pour plusieurs objets, qui doit impérativement être libérée avec delete[].
La comparaison entre pile et tas permet de distinguer la gestion automatique des variables locales de la gestion manuelle d’objets dont la taille et la durée de vie sont déterminées pendant l’exécution.
Le lecteur découvre aussi qu’une allocation peut échouer. Dans sa forme habituelle, new signale cet échec en lançant une exception de type std::bad_alloc.
Une attention particulière est enfin accordée aux fuites de mémoire. Elles apparaissent lorsqu’une allocation reste active alors que le programme a perdu l’adresse nécessaire pour la retrouver et la libérer.
Le but général est donc d’apprendre le cycle complet de la mémoire dynamique : allocation, utilisation, libération et mise à zéro du pointeur, tout en évitant les pointeurs invalides et les fuites de mémoire.