Skip to content

std::make_unique and deep copy

起因

在阅读 wikipedia Opaque pointer 的 "C++ Example: d-pointer pattern" 时,其中给出的例子是典型的 "Copy constructor for a class with unique_ptr",按照 stackoverflow Copy constructor for a class with unique_ptr 中的说法,显然这种情况下是需要deep copy的,但是其中的实现是使用的std::make_unique,这个函数是否是deep copy呢?

stackoverflow Why std::make_unique calls copy constructor

I'm wondering why make_unique calls copy constructor but does not call default constructor.

#include <memory>
#include <iostream>

template<typename T1, typename T2, typename T3, typename  T4>
class Node
{
public:
    Node()
    {
        std::cout << "default\n";
    }

    ~Node()
    {
        std::cout << " Delete\n";
    }

    Node(const Node &other)
    {
        std::cout << "copy\n";
    }
};

int main()
{
    Node<int, int, int, int> test1; //Calling default Cons
    std::unique_ptr<Node<int, int, int, int>> test2 = std::make_unique<Node<int, int, int, int>>(test1); //Nothing called

    Node<int, int, int, int> *test3 = test2.get();
    Node<int, int, int, int> test4 = Node<int, int, int, int>(*test3); // Calling copy Cons

    std::unique_ptr<Node<int, int, int, int>> test5 = std::make_unique<Node<int, int, int, int>>(test4); //Calling copy Cons
}
// g++ --std=c++14 test.cpp

NOTE:

上述是完整的测试程序

测试环境: https://coliru.stacked-crooked.com/

编译指令为:

g++ -std=c++17  -Wall -pedantic -pthread main.cpp && ./a.out

输出为:

default
copy
copy
copy
 Delete
 Delete
 Delete
 Delete

可以看到,上述输出与提问者描述的不同,差异在:std::unique_ptr<Node<int, int, int, int>> test2 = std::make_unique<Node<int, int, int, int>>(test1);

在上述测试环境中,它会调用copy constructor。

For example in code shown above: Frist, we create Node object -> calling default constructor. Then we wrap this object into smart-pointer object -> no calls.

But if we make deep copy of Node object -> calling copy constructor And then wrap copy into smart-pointer object-> calling copy constructor.

It's somehow connected to the creation of new control block?

A

std::unique_ptr<Node<int,int,int,int>> test5 = 
   std::make_unique<Node<int,int,int,int>(test4);// You copy from test4

std::make_unique creates a new pointer. It doesn't reuse an existing pointer. So since test4 is already there, it has to copy it. After test5 is constructed, test4 is still there (so can't do a move) and test5 is holding a new object, copied from test4.

wikipedia Opaque pointer

NOTE: 在这篇文章中也给出了例子,它被收录在 Opaque-data-type\Opaque-pointer 章节