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?
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.
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()