web-dev-qa-db-fra.com

Un unique_ptr peut-il prendre une valeur nullptr?

Ce fragment de code est-il valide? :

unique_ptr<A> p(new A());
p = nullptr;

Autrement dit, puis-je affecter nullptr à un unique_ptr? ou ça va échouer?

J'ai essayé cela avec le compilateur g ++ et cela a fonctionné, mais qu'en est-il des autres compilateurs?

21
Zhen

Cela fonctionnera.

À partir des paragraphes 20.7.1.2.3/8-9 de la norme C++ 11 sur le modèle de classe unique_ptr<>:

unique_ptr& operator=(nullptr_t) noexcept;

Effets : reset().

Postcondition : get() == nullptr

Cela signifie que la définition du modèle de classe unique_ptr<> Inclut une surcharge de operator = Qui accepte une valeur de type nullptr_t (Comme nullptr) comme main droite côté; le paragraphe spécifie également que l'attribution de nullptr à un unique_ptr équivaut à réinitialiser le unique_ptr.

Ainsi, après cette affectation, votre objet A sera détruit.

35
Andy Prowl

Cas plus courant:

#include <iostream>
#include <string>
#include <memory>

class A {
public:
    A() {std::cout << "A::A()" << std::endl;}
    ~A() {std::cout << "A::~A()" << std::endl;}
};

class B {
public:
    std::unique_ptr<A> pA;
    B() {std::cout << "B::B()" << std::endl;}
    ~B() { std::cout << "B::~B()" << std::endl;}
};

int main()
{
    std::unique_ptr<A> p1(new A());

    B b;
    b.pA = std::move(p1);
}

Production:

A::A()
B::B()
B::~B()
A::~A()

Cet exemple de code peut être non intuitif:

#include <iostream>
#include <string>
#include <memory>

class A {
public:
    A() {std::cout << "A::A()" << std::endl;}
    ~A() {std::cout << "A::~A()" << std::endl;}
};

class B {
public:
    std::unique_ptr<A> pA;
    B() {std::cout << "B::B()" << std::endl;}
    ~B() 
    {
        if (pA)
        {
            std::cout << "pA not nullptr!" << std::endl;
            pA = nullptr; // Will call A::~A()
        }
        std::cout << "B::~B()" << std::endl;
    }
};

int main()
{
    std::unique_ptr<A> p1(new A());

    B b;
    b.pA = std::move(p1);
}

Production:

A::A()
B::B()
pA not nullptr!
A::~A()
B::~B()
1
mrgloom