Maîtriser la mémoire dynamique en C++ : Stack vs Heap expliqués
Une bonne compréhension de la façon dont la mémoire dynamique fonctionne vraiment en C++ est essentielle pour devenir un bon programmeur C++. La mémoire dans votre programme C++ est divisée en deux parties :
La pile (stack) : Toutes les variables déclarées à l'intérieur de la fonction prendront de la mémoire depuis la pile.
Le tas (heap) : C'est la mémoire inutilisée du programme et peut être utilisée pour allouer la mémoire dynamiquement lors de l'exécution du programme.
Souvent, vous n'êtes pas conscient à l'avance de la quantité de mémoire dont vous aurez besoin pour stocker une information particulière dans une variable définie et la taille de la mémoire requise peut être déterminée à l'exécution.
Vous pouvez allouer de la mémoire à l'exécution dans le tas pour une variable d'un type donné en utilisant un opérateur spécial en C++ qui retourne l'adresse de l'espace alloué. Cet opérateur s'appelle l'opérateur new.
Si vous n'avez plus besoin de mémoire allouée dynamiquement, vous pouvez utiliser l'opérateur delete, qui désalloue la mémoire qui était précédemment allouée par l'opérateur new.
Opérateurs new et delete
Voici la syntaxe générique pour utiliser l'opérateur new pour allouer de la mémoire dynamiquement pour n'importe quel type de données.
new type_de_données;
Ici, type_de_données pourrait être n'importe quel type de données intégré incluant un tableau ou n'importe quel type de données défini par l'utilisateur incluant une classe ou une structure. Commençons avec les types de données intégrés. Par exemple, nous pouvons définir un pointeur vers le type double et ensuite demander que la mémoire soit allouée au moment de l'exécution. Nous pouvons faire cela en utilisant l'opérateur new avec les instructions suivantes :
double* pvalue = NULL; // Pointeur initialisé à null pvalue = new double; // Demander de la mémoire pour la variable
La mémoire n'a peut-être pas été allouée avec succès, si le magasin libre a été utilisé. Il est donc de bonne pratique de vérifier si l'opérateur new retourne un pointeur NULL et de prendre les mesures appropriées comme ci-dessous :
double* pvalue = NULL;
if(!(pvalue = new double)) {
cout << "Erreur : mémoire insuffisante." << endl;
exit(1);
}
La fonction malloc() du C existe toujours en C++, mais il est recommandé d'éviter d'utiliser la fonction malloc(). L'avantage principal de new sur malloc() est que new n'alloue pas seulement la mémoire, il construit les objets qui est le but premier de C++.
À tout moment, quand vous sentez qu'une variable qui a été allouée dynamiquement n'est plus requise, vous pouvez libérer la mémoire qu'elle occupe dans le magasin libre avec l'opérateur 'delete' comme suit :
delete pvalue; // Libérer la mémoire pointée par pvalue
Mettons les concepts ci-dessus ensemble et formons l'exemple suivant pour montrer comment 'new' et 'delete' fonctionnent :
#include <iostream>
using namespace std;
int main() {
double* pvalue = NULL; // Pointeur initialisé à null
pvalue = new double; // Demander de la mémoire pour la variable
*pvalue = 29494.99; // Stocker la valeur à l'adresse allouée
cout << "Valeur de pvalue : " << *pvalue << endl;
delete pvalue; // libérer la mémoire
return 0;
}
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
Valeur de pvalue : 29495
Allocation dynamique de mémoire pour les tableaux
Considérez que vous voulez allouer de la mémoire pour un tableau de caractères, c'est-à-dire une chaîne de 20 caractères. En utilisant la même syntaxe que celle utilisée ci-dessus, nous pouvons allouer de la mémoire dynamiquement comme montré ci-dessous.
char* pvalue = NULL; // Pointeur initialisé à null pvalue = new char[20]; // Demander de la mémoire pour la variable
Pour supprimer le tableau que nous venons de créer, l'instruction ressemblerait à ceci :
delete[] pvalue; // Supprimer le tableau pointé par pvalue
En suivant la syntaxe générique similaire de l'opérateur new, vous pouvez allouer pour un tableau multidimensionnel comme suit :
double** pvalue = NULL; // Pointeur initialisé à null pvalue = new double[3][4]; // Allouer de la mémoire pour un tableau 3x4
Cependant, la syntaxe pour libérer la mémoire pour un tableau multidimensionnel restera la même que ci-dessus :
delete[] pvalue; // Supprimer le tableau pointé par pvalue
Allocation dynamique de mémoire pour les objets
Les objets ne sont pas différents des types de données simples. Par exemple, considérez le code suivant où nous allons utiliser un tableau d'objets pour clarifier le concept :
#include <iostream>
using namespace std;
class Box {
public:
Box() {
cout << "Constructeur appelé !" << endl;
}
~Box() {
cout << "Destructeur appelé !" << endl;
}
};
int main() {
Box* myBoxArray = new Box[4];
delete[] myBoxArray; // Supprimer le tableau
return 0;
}
Si vous allouiez un tableau de quatre objets Box, le constructeur simple serait appelé quatre fois et de même lors de la suppression de ces objets, le destructeur sera aussi appelé le même nombre de fois.
Si nous compilons et exécutons le code ci-dessus, cela produirait le résultat suivant :
Constructeur appelé ! Constructeur appelé ! Constructeur appelé ! Constructeur appelé ! Destructeur appelé ! Destructeur appelé ! Destructeur appelé ! Destructeur appelé !
Langue C
- Comprendre les types de données C++ : Fondamentaux, modificateurs et bonnes pratiques
- Maîtriser les opérateurs C++ : Guide complet avec exemples pratiques
- Commentaires C++ : Bonnes pratiques pour un code lisible et maintenable
- Gestion de la mémoire dynamique en C : calloc, malloc et free expliqués
- Langage C++ : Vue d'ensemble et caractéristiques clés
- Constantes et littéraux en C++ : Types, syntaxe et bonnes pratiques
- Guide complet des opérateurs C++ : Types, utilisation et bonnes pratiques
- Maîtriser les types numériques en C++ : Guide pratique
- Comprendre les références en C++ : Concepts clés et différences avec les pointeurs