Classes de Stockage en C++

Salut à toi, aspirant(e)s programmeur(euse)s ! Aujourd'hui, nous allons entreprendre un voyage passionnant à travers le monde des classes de stockage en C++. Ne t'inquiète pas si tu es nouveau dans le domaine de la programmation ; je vais être ton guide amical, expliquant tout étape par étape. Mettons-nous à l'eau !

C++ Storage Classes

Quelles sont les Classes de Stockage ?

Avant de rentrer dans les détails, comprehensionnons ce qu'are les classes de stockage. En C++, les classes de stockage définissent la portée (visibilité) et la durée de vie des variables et des fonctions au sein d'un programme. Elles indiquent au compilateur comment stocker la variable, si elle est accessible depuis d'autres fichiers, et combien de temps elle devrait exister en mémoire.

Maintenant, explorons chaque classe de stockage en détail.

La Classe de Stockage auto

Le mot-clé auto en C++ a changé de signification au fil du temps. Dans le C++ moderne (C++11 et suivant), il est utilisé pour l'inférence de type. Cependant, dans les versions plus anciennes, il était un spécificateur de classe de stockage.

Ancienne utilisation (avant C++11) :

int main() {
auto int x = 5;  // Équivalent à : int x = 5;
return 0;
}

Dans cette ancienne utilisation, auto déclarait explicitement une variable avec une durée de stockage automatique. Cependant, c'était la valeur par défaut pour les variables locales, donc il était rarement utilisé.

Utilisation moderne (C++11 et suivant) :

int main() {
auto x = 5;  // x est inféré comme un int
auto y = 3.14;  // y est inféré comme un double
auto z = "Hello";  // z est inféré comme un const char*
return 0;
}

Dans le C++ moderne, auto permet au compilateur de déduire le type de la variable en fonction de son initialisateur. C'est particulièrement utile avec des types complexes ou lorsque le type pourrait changer à l'avenir.

La Classe de Stockage register

Le mot-clé register est un hint au compilateur que cette variable sera utilisée fréquemment et devrait être conservée dans un registre CPU pour un accès plus rapide.

#include <iostream>

int main() {
register int counter = 0;

for(int i = 0; i < 1000000; i++) {
counter++;
}

std::cout << "Compteur : " << counter << std::endl;
return 0;
}

Dans cet exemple, nous suggérons au compilateur que counter devrait être conservé dans un registre. Cependant, les compilateurs modernes sont généralement suffisamment intelligents pour faire ces optimisations d'eux-mêmes, donc register est rarement utilisé en pratique.

La Classe de Stockage static

Le mot-clé static a des significations différentes en fonction de son utilisation :

1. Variables Locales Statiques

#include <iostream>

void countCalls() {
static int calls = 0;
calls++;
std::cout << "Cette fonction a été appelée " << calls << " fois." << std::endl;
}

int main() {
for(int i = 0; i < 5; i++) {
countCalls();
}
return 0;
}

Dans cet exemple, calls est initialisée une seule fois et conserve sa valeur entre les appels de fonction. La sortie sera :

Cette fonction a été appelée 1 fois.
Cette fonction a été appelée 2 fois.
Cette fonction a été appelée 3 fois.
Cette fonction a été appelée 4 fois.
Cette fonction a été appelée 5 fois.

2. Membres de Classe Statiques

class MyClass {
public:
static int objectCount;

MyClass() {
objectCount++;
}
};

int MyClass::objectCount = 0;

int main() {
MyClass obj1;
MyClass obj2;
MyClass obj3;

std::cout << "Nombre d'objets créés : " << MyClass::objectCount << std::endl;
return 0;
}

Ici, objectCount est partagée entre toutes les instances de MyClass. La sortie sera :

Nombre d'objets créés : 3

La Classe de Stockage extern

Le mot-clé extern est utilisé pour déclarer une variable ou une fonction globale dans un autre fichier.

Fichier : globals.cpp

int globalVar = 10;

Fichier : main.cpp

#include <iostream>

extern int globalVar;  // Déclaration de globalVar

int main() {
std::cout << "Valeur de la variable globale : " << globalVar << std::endl;
return 0;
}

Dans cet exemple, globalVar est définie dans globals.cpp et déclarée comme extern dans main.cpp. Cela permet à main.cpp d'utiliser la variable définie dans un autre fichier.

La Classe de Stockage mutable

Le mot-clé mutable permet à un membre d'un objet const d'être modifié.

class Person {
public:
Person(int age) : age(age), cacheValid(false) {}

int getAge() const {
if (!cacheValid) {
cachedAge = heavyComputation();
cacheValid = true;
}
return cachedAge;
}

private:
int age;
mutable int cachedAge;
mutable bool cacheValid;

int heavyComputation() const {
// Simuler un calcul lourd
return age;
}
};

int main() {
const Person p(30);
std::cout << p.getAge() << std::endl;  // Cela est permis
return 0;
}

Dans cet exemple, même si p est const, nous pouvons modifier cachedAge et cacheValid car ils sont marqués comme mutable.

Résumé

Résumons les classes de stockage que nous avons apprises dans un tableau pratique :

Classe de Stockage Objectif
auto Inférence de type (C++ moderne)
register Hint pour un accès plus rapide (rarement utilisé)
static Préserver la valeur entre les appels de fonction ou partagée entre les instances de classe
extern Déclarer des variables ou des fonctions d'autres fichiers
mutable Permettre la modification dans les objets const

Souviens-toi, comprendre les classes de stockage est crucial pour gérer la mémoire efficacement et contrôler la portée de tes variables. Alors que tu continues ton parcours en C++, tu trouveras ces concepts devenant naturels. Bon codage !

Credits: Image by storyset