为什么要对 std::make_unique 进行一组额外的构造函数/析构函数调用?

Suh*_*sis 0 c++ unique-ptr c++14

看起来 std::make_unique 正在制作额外的副本(相关帖子),而它应该更有效。下面是具有典型 C++ 多态类架构的示例实现。代码片段下面提到的输出显示,如果我们取消对 make_unique 调用的注释,它会调用一对额外的 ctor/dtor。

class Shape
{
public:
    Shape() { cout << "Shape::ctor\n"; }
    virtual ~Shape() {cout << "Shape::dtor\n";}
};

class Rectangle : public Shape
{
public:
    Rectangle() {cout << "Rectangle::ctor\n";}
    virtual ~Rectangle() {cout << "Rectangle::dtor\n";}
};

unique_ptr<Shape> makeShape(int type) 
{
    //unique_ptr<Shape> spShape = make_unique<Shape>(); //extra ctor call
    unique_ptr<Shape> spShape(nullptr);
    switch (type)
    {
    case 1: //rect
        spShape.reset(new Rectangle());
        break;   
    default:
        break;
    }
    return spShape;
}

int main(int argc, char const *argv[])
{
    auto shape1 = makeShape(1);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)
==========================
output with make_unique
--------------------------
Shape::ctor
Shape::ctor
Rectangle::ctor
Shape::dtor
Rectangle::dtor
Shape::dtor
--------------------------
output w/o make_unique
--------------------------
Shape::ctor
Rectangle::ctor
Rectangle::dtor
Shape::dtor
--------------------------
Run Code Online (Sandbox Code Playgroud)

make_unique 不适用于自定义删除器。那么使用它有什么好处呢?

Die*_*Epp 5

不会std::make_unique<Shape>()创建 null unique_ptr。相反,它相当于:

\n
unique_ptr<Shape> makeShape(int type) \n{\n    unique_ptr<Shape> spShape(new Shape); //extra ctor call\n    switch (type)\n    {\n    case 1: //rect\n        // Must destroy old spShape here.\n        spShape.reset(new Rectangle());\n        break;   \n    default:\n        break;\n    }\n    return spShape;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

如果您不想创建对象,请不要使用std::make_unique. 的目的std::make_unique是构造对象并std::unique_ptr一步完成。

\n
\n

[make_unique] 应该更有效 [...]

\n
\n

不它不是。如果您使用临时对象构造对象,它应该会更安全。看:

\n

std::make_unique 和 std::unique_ptr 与 new 之间的差异

\n

清理后的代码:

\n

我可能会这样写:

\n
std::unique_ptr<Shape> makeShape(int type) {\n    switch (type) {\n    case 1:\n        return std::make_unique<Rectangle>();\n    default:\n        return std::make_unique<Shape>();\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n