Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Notre page Facebook
Notre groupe Facebook


Android Game
Alien Attacks - Android Game

Utilisation de la classe std::unique_ptr

Accès rapide :
      Présentation de la classe
      Exemple d'utilisation de la classe

Présentation de la classe

Les classes de pointeurs malins (smart pointers) fournies en standard dans la librairie C++ sont accessible via l'entête <memory>. C'est notamment le cas de la classe std::unique_ptr. Il est néanmoins à noter que cette classe est disponible depuis la version 2011 du standard C++ (l'option -std=c++11 est donc requise pour compiler avec g++).

La classe std::unique_ptr respecte le principe RAII (Resource Acquisition Is Initialization - voir la page d'introduction à ce chapitre à ce sujet) en garantissant que la durée de vie de votre pointeur et de la zone de mémoire associée sont liés à la durée de vie de l'instance de pointeur malin. Dés que celui-ci disparait, la zone de mémoire est automatiquement relachée.

Par contre, comme son nom l'indique, l'association entre le pointeur sur la ressource à relâcher et l'instance de type std::unique_ptr est unique. Les instances de type std::unique_ptr ne pourront donc pas être dupliquées (contrairement à des instances de types std::shared_ptr).

Remarque : cette classe provient du projet Boost. Son nom originel était boost::scoped_ptr. Cette information est importante pour ceux qui souhaiteraient utiliser cette classe avec une chaine de compilation antérieur au standard C++11.

Exemple d'utilisation de la classe

Reprenons notre classe de ressources vu dans la page précédente. En revoici, a titre de rappel, la déclaration et l'implémentation.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
#ifndef __RESOURCE
#define __RESOURCE

#include <memory>
#include <string>



class Resource {
    std::string name;

public:
    Resource( const std::string & name );
    ~Resource();

    void doSomething();
};

typedef std::unique_ptr< Resource > ResourcePtr;

#endif
Resource.h : déclaration de notre classe qui va être prise en charge par nos pointeurs malins

Notez la définition du typedef afin de simplifier l'utilisation de la classe de pointeurs malins. Et voici maintenant le fichier d'implémentation de notre classe.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
#include <iostream>

using namespace std;

#include "Resource.h"


Resource::Resource( const std::string & name ) : name( name ) {
    cout << "Resource " << name << " created" << endl;
}


Resource::~Resource() {
    cout << "Resource " << name << " released" << endl;
}


void Resource::doSomething() {
    cout << "Resource " << name << " used" << endl;
}
Resource.cpp : implémentation de notre classe

Et voici maintenant un exemple d'utilisation de notre classe de ressource au travers de pointeurs malins de type std::unique_ptr.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
 23 
 24 
#include <iostream>

using namespace std;

#include "Resource.h"


int main(int argc, char * argv[]) {

    ResourcePtr ptr1( new Resource( "Demo" ) );
    ptr1->doSomething();

    // Les lignes de code suivantes ne compilent pas
    /*

    ResourcePtr ptr2;            // Basé sur nullptr
    ptr2 = ptr1;                // Copie impossible

    ResourcePtr ptr3( ptr1 );    // Copie impossible

    */

    return 0;
}
main.cpp : un exemple d'utilisation de std::unique_ptr

Compilons maintenant notre programme et lançons-le.

$> g++ -std=c++14 *.cpp -o raii
$> raii
Resource Demo created
Resource Demo used
Resource Demo released
$>

Si vous tentez de compiler les lignes commentées vous produirez les messages d'erreurs suivants :

$> g++ -std=c++14 *.cpp -o raii
UseResource.cpp: Dans la fonction 'int main(int, char**)':
UseResource.cpp:17:10: erreur: use of deleted function 'std::unique_ptr<_Tp, _Dp>& std::unique_ptr<_Tp, _Dp>::operator=(
const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Resource; _Dp = std::default_delete<Resource>]'
     ptr2 = ptr1;                // Copie impossible
          ^
In file included from /usr/include/c++/5.3.1/memory:81:0,
                 from Resource.h:4,
                 from UseResource.cpp:5:
/usr/include/c++/5.3.1/bits/unique_ptr.h:357:19: note: declared here
       unique_ptr& operator=(const unique_ptr&) = delete;
                   ^

UseResource.cpp:19:28: erreur: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) 
[with _Tp = Resource; _Dp = std::default_delete<Resource>]'
     ResourcePtr ptr3( ptr1 );    // Copie impossible
                            ^
In file included from /usr/include/c++/5.3.1/memory:81:0,
                 from Resource.h:4,
                 from UseResource.cpp:5:
/usr/include/c++/5.3.1/bits/unique_ptr.h:356:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;
       ^
$>

Mise en oeuvre d'une classe de « smart pointers » <<
>> Utilisation de la classe std::shared_ptr