Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a unique_ptr take a nullptr value?

Is this code fragment valid? :

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

That is, can I assign nullptr to a unique_ptr ? or it will fail?

I tried this with the g++ compiler and it worked, but what about other compilers?

like image 944
Zhen Avatar asked Feb 25 '13 15:02

Zhen


People also ask

Can a unique_ptr be nullptr?

nullptr is a keyword new in C++11 for better support of null pointers. unique_ptr can be constructed from nullptr , even implicitly.

Can I dereference a unique_ptr?

The unique_ptr shall not be empty (i.e., its stored pointer shall not be a null pointer) in order to be dereferenciable. This can easily be checked by casting the unique_ptr object to bool (see unique_ptr::operator bool). It is equivalent to: *get().

Can unique_ptr be copied?

A unique_ptr does not share its pointer. It cannot be copied to another unique_ptr , passed by value to a function, or used in any C++ Standard Library algorithm that requires copies to be made. A unique_ptr can only be moved.


2 Answers

It will work.

From Paragraphs 20.7.1.2.3/8-9 of the C++11 Standard about the unique_ptr<> class template:

unique_ptr& operator=(nullptr_t) noexcept;

Effects: reset().

Postcondition: get() == nullptr

This means that the definition of class template unique_ptr<> includes an overload of operator = that accepts a value of type nullptr_t (such as nullptr) as its right hand side; the paragraph also specifies that assigning nullptr to a unique_ptr is equivalent to resetting the unique_ptr.

Thus, after this assignment, your A object will be destroyed.

like image 88
Andy Prowl Avatar answered Oct 03 '22 16:10

Andy Prowl


More common case:

#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);
}

Output:

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

This code example can be non-intuitive:

#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);
}

Output:

A::A()
B::B()
pA not nullptr!
A::~A()
B::~B()
like image 29
mrgloom Avatar answered Oct 02 '22 16:10

mrgloom