在派生类上使用带有自定义删除器的 std::make_unique

Using std::make_unique with custom deleter on a derived class?

本文关键字:std make unique 删除 自定义 派生      更新时间:2023-10-16

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

我想将Base与名为 BaseDeleter 的自定义删除器一起放在unique_ptr中。这也允许我从分配给它的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上编译。(同上)
为什么这不起作用?怎么能用std::make_unique来分配这样的std::unique_ptr呢?

这是

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是删除程序的实例。

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

这与你问题中的基础/派生的复杂性无关,这是一个红鲱鱼。