在派生类上使用std :: make_unique和自定义删除器?

时间:2016-05-29 19:35:16

标签: c++ c++14 unique-ptr

我们假设我有一个名为Derived的类,它继承自一个名为Base的类。 Base很特别 - 虽然它可能是使用new创建的,但它必须通过自定义删除器进行破坏。

我希望Base中的unique_ptr以及名为BaseDeleter的自定义删除工具。这也允许我拥有从Base派生的其他类。出于例外安全性和一致性的考虑,我希望使用std::make_unique来协助我的unique_ptr

我创建了一个小片段,演示了我想要的内容:

#include <memory>

class Base
{
};

class Derived : public Base
{
};

struct BaseDeleter
{
    void operator()(Base* base)
    {
        // Perform some special deleting
    }
};

class Big
{
public:
    Big()
    {
        //pointer.reset(new Derived()); // This works!
        pointer = std::make_unique<Derived, BaseDeleter>(); // But this doesn't...
    }

private:
    std::unique_ptr<Base, BaseDeleter> pointer;
};

int main()
{
    Big clazz;
}

不幸的是,无法在Visual Studio 2015 Update 2和gcc-5.1上进行编译。 (ideone
为什么这不起作用?如何使用std::make_unique分配此类std::unique_ptr

2 个答案:

答案 0 :(得分:2)

Make unique不适用于自定义删除器。自己写或不使用它。

这与你的问题中的基础/派生并发症无关,这是一个红色的鲱鱼。

答案 1 :(得分:2)

这是make_unique的签名之一(我认为你希望使用的签名之一):

template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args );

其中T是您要创建的对象的类型,Args...是您要转发给构造函数的参数类型。

正如您所看到的,您无法使用智能指针的make_*辅助函数指示自定义删除器(既不是make_unique也不是make_shared)。

您必须显式构造指针,如下所示:

std::unique_ptr<T, D> ptr{new T{)};

如果删除器不是默认可构造的,则可以执行以下操作:

std::unique_ptr<T, D> ptr{new T{}, d};

其中d是删除器的实例。