C++ — Les bases
C++ n'est pas « du C amélioré »
C'est le premier malentendu à dissiper. C++, créé par Bjarne Stroustrup à partir de 1979, contient le C mais est un langage fondamentalement différent dans sa philosophie. Là où le C te donne un contrôle brut du métal, C++ ajoute des couches d'abstraction puissantes (objets, généricité, gestion automatique des ressources) tout en gardant la performance et l'accès bas niveau. On dit qu'il permet une programmation « zero-cost abstraction » : des abstractions de haut niveau qui ne coûtent rien en performance à l'exécution.
Pour ton profil : tu as déjà utilisé C++ sur STeaMi (ta trilatération BLE en C++ atteignait ~5 cm de précision contre ~20 cm en MicroPython — justement grâce à la performance du natif). C++ est le langage des systèmes où l'on veut à la fois performance maximale et abstractions modernes : moteurs de jeux, navigateurs, systèmes de trading haute fréquence, une grande partie des outils de sécurité performants.
Note importante : « C++ moderne » (depuis C++11, puis 14/17/20/23) est très différent du vieux C++ des années 2000. Ce cours vise le C++ moderne, qui est plus sûr et plus agréable. Compile avec un standard récent :
g++ -std=c++17 -Wall -Wextra programme.cpp -o programme
Ce que C++ garde du C, ce qu'il change
Tu retrouves les types, les pointeurs, les structs, le contrôle de flux du C. Mais dès le départ, des différences de confort :
#include <iostream> // entrées/sorties C++ (remplace stdio.h)
#include <string> // vraies chaînes (remplace les char*)
#include <vector> // tableaux dynamiques (remplace malloc)
int main() {
std::string nom = "Matteo"; // une VRAIE chaîne, pas un char[]
std::cout << "Bonjour " << nom << "\n"; // sortie avec <<
std::cout << "Ton âge ? ";
int age;
std::cin >> age; // entrée avec >>
std::cout << "Dans 10 ans : " << age + 10 << "\n";
return 0;
}
Trois gains immédiats sur le C :
std::stringgère les chaînes sans les pièges deschar*(plus de buffer overflow sur les chaînes, redimensionnement automatique).std::cout <</std::cin >>sont typés (pas de%d/%sà faire correspondre comme enprintf, source de bugs).std::vectorremplace l'allocation manuelle avecmalloc/free.
Le std:: est le namespace de la bibliothèque standard (voir plus bas).
Les conteneurs de la STL : ne plus jamais gérer la mémoire à la main
La STL (Standard Template Library) fournit des structures de données prêtes à l'emploi qui gèrent leur mémoire automatiquement. C'est un des plus grands atouts de C++ sur le C.
#include <vector>
#include <map>
#include <set>
#include <string>
// vector : tableau dynamique (l'équivalent de la list Python)
std::vector<int> ports = {22, 80, 443};
ports.push_back(8080); // ajoute (redimensionne tout seul)
std::cout << ports.size() << "\n"; // 4
std::cout << ports[0] << "\n"; // 22
// map : dictionnaire trié (clé → valeur)
std::map<std::string, int> services;
services["ssh"] = 22;
services["http"] = 80;
std::cout << services["ssh"] << "\n"; // 22
// set : ensemble sans doublons
std::set<std::string> ips_vues;
ips_vues.insert("10.0.0.1");
ips_vues.insert("10.0.0.1"); // ignoré (doublon)
std::cout << ips_vues.size() << "\n"; // 1
Fini le malloc/free manuel du C pour ces cas courants : std::vector alloue et libère automatiquement. C'est plus sûr (pas de fuite, pas de buffer overflow) et aussi rapide.
Il existe aussi std::unordered_map et std::unordered_set (versions à base de table de hachage, plus rapides en accès mais non triées).
Parcourir les conteneurs
std::vector<int> ports = {22, 80, 443};
// Boucle "range-based for" (moderne, lisible) — comme le for de Python
for (int port : ports) {
std::cout << port << "\n";
}
// Avec référence pour modifier, et auto pour le type
for (auto& port : ports) {
port *= 2; // modifie les éléments
}
// Sur une map
std::map<std::string, int> services = {{"ssh", 22}, {"http", 80}};
for (const auto& [nom, port] : services) { // structured bindings (C++17)
std::cout << nom << " -> " << port << "\n";
}
Le auto laisse le compilateur déduire le type — pratique et lisible. Le for (const auto& [cle, valeur] : map) (structured bindings) est l'équivalent élégant du for cle, valeur in dict.items() de Python.
Les classes : la POO en C++
C++ ajoute au C une programmation orientée objet complète :
class Hote {
private: // accessible seulement dans la classe
std::string ip;
std::vector<int> ports_ouverts;
public: // accessible de l'extérieur
// Constructeur
Hote(const std::string& adresse) : ip(adresse) {}
void ajouter_port(int port) {
ports_ouverts.push_back(port);
}
int nombre_ports() const { // const = ne modifie pas l'objet
return ports_ouverts.size();
}
std::string get_ip() const {
return ip;
}
};
int main() {
Hote h("192.168.1.1");
h.ajouter_port(22);
h.ajouter_port(80);
std::cout << h.get_ip() << " : " << h.nombre_ports() << " ports\n";
}
Deux notions clés dès les bases :
L'encapsulation (private / public) — on cache les données internes (private) et on expose une interface contrôlée (public). Ça protège l'état de l'objet contre les modifications incohérentes.
Le mot-clé const — sur une méthode, il garantit qu'elle ne modifie pas l'objet. C'est une forme de sécurité à la compilation : le compilateur refuse toute modification accidentelle. Utilise const partout où c'est possible, c'est une marque de code C++ de qualité.
RAII : le concept qui change tout
Voici LE concept fondamental de C++, celui qui le distingue vraiment. RAII = Resource Acquisition Is Initialization. L'idée : une ressource (mémoire, fichier, connexion réseau, mutex) est liée à la durée de vie d'un objet. Quand l'objet est créé, il acquiert la ressource ; quand il est détruit (automatiquement, en sortant de sa portée), il la libère.
#include <fstream>
void traiter() {
std::ifstream fichier("data.txt"); // ouvre le fichier (acquisition)
// ... utilise le fichier ...
} // <- ici, le fichier est fermé AUTOMATIQUEMENT (destruction)
// même si une exception est levée
Compare avec le C, où tu dois te souvenir de fclose() à chaque chemin de sortie (et où oublier = fuite). En C++, le destructeur de l'objet s'exécute automatiquement quand il sort de sa portée, garantissant la libération. C'est ce qui permet à C++ d'être sûr sans garbage collector : la libération est déterministe et automatique.
RAII s'applique à tout : std::vector libère sa mémoire, std::lock_guard libère un mutex, std::unique_ptr libère un pointeur. On approfondit dans l'avancé, mais retiens dès maintenant : en C++ moderne, on ne fait quasiment plus de new/delete manuels — RAII s'en charge.
Les namespaces
Pour éviter les collisions de noms dans les gros projets, C++ organise le code en namespaces :
namespace reseau {
int port_defaut = 8080;
void connecter() { /* ... */ }
}
reseau::connecter(); // appel qualifié
std::cout << reseau::port_defaut;
// using pour éviter de répéter le préfixe
using namespace std; // à ÉVITER en global (pollue l'espace de noms)
Le std:: que tu vois partout est le namespace de la bibliothèque standard. Beaucoup de débutants mettent using namespace std; pour s'épargner les std::, mais c'est déconseillé dans du vrai code (risque de collisions) : garde les std:: explicites.
Références : des pointeurs sans les dangers
C++ introduit les références, un alias vers une variable existante, plus sûr que les pointeurs du C :
int x = 42;
int& ref = x; // ref est un autre nom pour x
ref = 100;
std::cout << x; // 100
// Passage par référence à une fonction (modifie l'original, sans pointeur)
void doubler(int& n) {
n *= 2;
}
int val = 21;
doubler(val); // pas besoin de &val comme en C
std::cout << val; // 42
// Référence const : passer un gros objet sans le copier, sans risque de modif
void afficher(const std::string& texte) { // pas de copie, lecture seule
std::cout << texte;
}
Une référence ne peut pas être nulle et ne peut pas être réassignée — donc pas de risque de pointeur nul ou de dangling comme avec les pointeurs C. Le pattern const std::string& en paramètre (passer par référence constante) est idiomatique : il évite de copier de gros objets tout en garantissant qu'ils ne seront pas modifiés.
Ce qu'il faut retenir
- C++ n'est pas du C amélioré : c'est un langage à part, qui ajoute des abstractions puissantes sans sacrifier la performance (zero-cost abstraction). Vise le C++ moderne (C++17+).
- La STL (
std::vector,std::map,std::set,std::string) remplace la gestion mémoire manuelle du C — plus sûr, aussi rapide. - Parcours avec le range-based for (
for (auto& x : conteneur)) et les structured bindings (for (auto& [k,v] : map)). - Les classes apportent l'encapsulation (
private/public) ; utiliseconstpartout où c'est possible. - RAII est LE concept clé : les ressources sont liées à la durée de vie des objets et libérées automatiquement à la destruction — sécurité mémoire sans garbage collector.
- Les namespaces (
std::, les tiens) évitent les collisions ; garde lesstd::explicites. - Les références (
int&,const std::string&) sont des pointeurs sûrs, idéales pour passer des objets sans copie.