Programmation • IoT

Chapitre 2 – std::unique_ptr et la propriété exclusive

Document réservé

Vous consultez actuellement la présentation publique de ce chapitre.

Les documents PDF complets, comprenant les développements théoriques, les exemples détaillés et les exercices, sont disponibles sur demande.

Pour obtenir un accès, contactez-moi via la page Contact en indiquant les domaines qui vous intéressent (C++, ESP-IDF, électronique, etc.).

2 std::unique_ptr et la propriété exclusive 2.1 Du principe RAII à std::unique_ptr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.5 Un unique_ptr peut posséder un objet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.6 Que se passe-t-il lors d’une sortie anticipée ? . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.7.1 Le compilateur refuse la copie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.8 Mais peut-on changer de propriétaire ? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2026 – C++ Partie III std::unique_ptr et la propriété exclusive
Accueil
std::unique_ptr et la propriété exclusive Du principe RAII à std::unique_ptr Dans le chapitre précédent, nous avons vu qu’une ressource peut être confiée à un objet chargé de la libérer lorsque sa durée de vie se termine. C’est le principe RAII. Nous avons cependant rencontré un problème avec notre classe Tableau : La copie de l’objet pouvait conduire à la copie du pointeur interne et deux objets pouvaient alors contenir l’adresse de la même zone de mémoire et tenter tous les deux de la libérer. Le problème fondamental n’était donc plus seulement : Qui libère la ressource ? Qui possède la ressource ? Le C++ moderne fournit plusieurs outils permettant d’exprimer explicitement cette notion de propriété. Le plus simple et le plus important est : Le terme unique est essentiel : Un std::unique_ptr représente la propriété exclusive d’une ressource. Autrement dit, à un instant donné, une ressource gérée par un unique_ptr possède un unique propriétaire. Notre premier unique_ptr Pour utiliser std::unique_ptr, nous devons inclure dans notre programme. 2026 – C++ Partie III std::unique_ptr et la propriété exclusive std::unique_ptr<int> p(new int(42)); std::cout << *p << ’\n’; std::unique_ptr<int> p(new int(42)); crée un objet p capable de posséder un objet de type int. alloue dynamiquement un entier et l’initialise avec la valeur 42 et l’adresse obtenue est confiée au unique_ptr. Nous pouvons représenter la situation ainsi : Le pointeur intelligent p est maintenant le propriétaire de cet entier. Accéder à la valeur Comme avec un pointeur classique, l’opérateur * permet d’accéder à l’objet possédé : std::cout << *p << ’\n’; Nous pouvons également modifier cette valeur : std::cout << *p << ’\n’; Où est passé delete ? C’est ici que le principe RAII intervient, considérons :
Accueil
2026 – C++ Partie III std::unique_ptr et la propriété exclusive std::unique_ptr<int> p(new int(42)); std::cout << *p << ’\n’; Lorsque l’exécution atteint la fin de la fonction, l’objet p est détruit càd que le destructeur de unique_ptr libère automatiquement l’objet dynamique qu’il possède et il n’est pas nécessaire d’écrire : Cette instruction serait d’ailleurs incorrecte car p n’est pas un pointeur brut de type int*, mais un objet std::unique_ptr<int> La destruction peut être représentée ainsi : destruction de la ressource possédée libération automatique de la mémoire • Un std::unique_ptr possède la ressource qui lui a été confiée. • Lorsque le unique_ptr est détruit, sa ressource est automatiquement détruite et la mémoire correspondante est libérée. • Il ne faut donc pas appeler manuellement delete sur la ressource possédée. L’écriture précédente fonctionne, càd que std::unique_ptr<int> p(new int(42)); est valable, mais le C++ moderne fournit une manière plus sûre de construire un unique_ptr : auto p = std::make_unique<int>(42); La fonction std::make_unique crée l’objet dynamique et retourne directement un unique_ptr qui en devient propriétaire. Pour l’utiliser, il faut également mettre Nous pouvons donc écrire auto p = std::make_unique<int>(42); std::cout << *p << ’\n’;
Accueil
2026 – C++ Partie III std::unique_ptr et la propriété exclusive std::make_unique<int>(42) construit un entier contenant 42 et place immédiatement sa gestion sous la responsabilité d’un unique_ptr. L’utilisation de auto n’est pas obligatoire car nous pouvons écrire explicitement std::unique_ptr<int> p = std::make_unique<int>(42); Le type de p est donc : std::unique_ptr<int> L’écriture avec auto : auto p = std::make_unique<int>(42); évite simplement de répéter une information que le compilateur peut déduire. • En C++ moderne, on préférera généralement : auto p = std::make_unique<int>(42); std::unique_ptr<int> p(new int(42)); • La ressource est ainsi créée directement sous le contrôle du unique_ptr. Un unique_ptr peut posséder un objet L’intérêt de unique_ptr ne se limite évidemment pas aux types fondamentaux. En effet, considérons une classe simple comme : Point(double x0, double y0)
Accueil
2026 – C++ Partie III std::unique_ptr et la propriété exclusive Nous pouvons créer dynamiquement un objet Point : auto p = std::make_unique<Point>(3.0, 4.0); L’objet Point est créé dynamiquement et p en devient l’unique propriétaire. Comme avec un pointeur classique, nous pouvons utiliser l’opérateur -> pour accéder aux membres de std::cout << p->getX() << ’\n’; std::cout << p->getY() << ’\n’; Nous pouvons donc utiliser un unique_ptr d’une manière très proche d’un pointeur classique : accès à l’objet possédé, accès à un membre de l’objet possédé. La différence fondamentale ne concerne donc pas principalement l’accès à l’objet, mais elle concerne sa propriété et sa durée de vie. Que se passe-t-il lors d’une sortie anticipée ? Reprenons maintenant le problème rencontré avec l’allocation manuelle, c.-à-d. la fuite de données. auto p = std::make_unique<int>(42); // Autres calculs… Si erreur est vraie, la fonction se termine avec return, mais avant de quitter la portée, l’objet local p est détruit autrement dit, son destructeur libère automatiquement la ressource qu’il possède. Nous retrouvons donc exactement le principe RAII étudié dans le chapitre précédent. fin de la durée de vie de p libération de sa ressource Le même principe s’applique lorsqu’une exception provoque la sortie de la portée.
Accueil
2026 – C++ Partie III std::unique_ptr et la propriété exclusive Peut-on copier un unique_ptr ? Nous arrivons maintenant au problème qui avait mis en difficulté notre première classe RAII. Créons un premier pointeur intelligent : auto p1 = std::make_unique<int>(42); Que devrait faire le programme ? Si la copie était autorisée, nous pourrions obtenir : Deux objets prétendraient alors être propriétaires de la même ressource et cela contredirait directement le principe de propriété exclusive de unique_ptr. Le compilateur refuse la copie Essayons le programme suivant : auto p1 = std::make_unique<int>(42); Le programme ne compile pas, ce n’est pas une limitation accidentelle de unique_ptr mais c’est au contraire une propriété fondamentale de sa conception. Un unique_ptr ne peut pas être copié. Le compilateur nous empêche ainsi de créer accidentellement deux propriétaires de la même ressource. • La propriété représentée par std::unique_ptr est exclusive. • Un unique_ptr ne peut donc pas être copié. • Cette interdiction est vérifiée par le compilateur : une erreur de conception susceptible de provoquer une mauvaise gestion de la ressource est ainsi détectée avant même l’exécution du Mais peut-on changer de propriétaire ? L’interdiction de copier pose immédiatement une nouvelle question, celle du changement de propriétaire.
Accueil
2026 – C++ Partie III std::unique_ptr et la propriété exclusive auto p1 = std::make_unique<int>(42); soit propriétaire de la ressource. Nous voulons maintenant que cette ressource appartienne à un autre unique_ptr, nommé p2. Nous ne voulons pas obtenir deux propriétaires mais effectuer : avec p1 qui ne possède plus rien. Il ne s’agit donc pas de copier la propriété mais de la transférer et cette distinction entre copie et transfert constitue l’une des évolutions majeures introduites par le C++ moderne. Elle nous conduira à étudier la sémantique de déplacement et notamment Avant d’aller plus loin avec unique_ptr, nous devons donc comprendre ce que signifie réellement déplacer
Accueil
P4-Chap-02 std::unique_ptr et la propriété exclusive
Accueil
Termes à ajouter au glossaire
Contenu

Inscription

×
Cancel