Этот фрагмент кода действителен? :
unique_ptr<A> p(new A());
p = nullptr;
То есть я могу назначить nullptr
для unique_ptr
? или не получится?
Я попробовал это с компилятором g++, и это сработало, но как насчет других компиляторов?
Этот фрагмент кода действителен? :
unique_ptr<A> p(new A());
p = nullptr;
То есть я могу назначить nullptr
для unique_ptr
? или не получится?
Я попробовал это с компилятором g++, и это сработало, но как насчет других компиляторов?
Он будет работать.
Из параграфов 20.7.1.2.3/8-9 стандарта С++ 11 о шаблоне класса unique_ptr<>
:
unique_ptr& operator=(nullptr_t) noexcept
;Эффекты:
reset()
.Постусловие:
get() == nullptr
Это означает, что определение шаблона класса unique_ptr<>
включает в себя перегрузку operator =
, которая принимает значение типа nullptr_t
(например, nullptr
) как правую сторону; в параграфе также указывается, что присвоение nullptr
a unique_ptr
эквивалентно сбросу unique_ptr
.
Таким образом, после этого назначения ваш объект A
будет уничтожен.
Наиболее распространенный случай:
#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);
}
Выход:
A::A()
B::B()
B::~B()
A::~A()
Этот пример кода может быть не интуитивным:
#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);
}
Выход:
A::A()
B::B()
pA not nullptr!
A::~A()
B::~B()