std :: unique_ptr的自定义删除器是否是手动调用析构函数的有效位置?

时间:2014-01-14 10:28:24

标签: c++ c++11 destructor unique-ptr incomplete-type

我有一个非常基本的反射实现,它包含一个Type类,它为它描述的类进行对象实例化。剥离到相关部分,它看起来像这样:

Type.h:

class Plugin; // forward declaration

typedef std::unique_ptr<Plugin> PluginPtr;

namespace Reflection {

    class Type {
    public:
        explicit Type(PluginPtr(*)());
        PluginPtr CreateInstance();
    private:
        PluginPtr(*_createInstance_Handler)();
    };

}

Type.cpp:

Type::Type(PluginPtr(*createInstance_Handler)()) :
    _createInstance_Handler(createInstance_Handler) {}

PluginPtr CreateInstance() { return (*_createInstance_Handler)(); }

实际的实例化逻辑位于Plugin类(以及每个后代)中:

Plugin.h:

class Plugin {
public:
    virtual ~Plugin();
    static const Reflection::Type Type;
private:
    static PluginPtr CreateInstance();

Plugin.cpp

Plugin::~Plugin() {}

const Reflection::Type Plugin::Type(CreateInstance);

PluginPtr Plugin::CreateInstance() { return PluginPtr(new Plugin); }

当我尝试编译它时,我得到了这些错误(在Visual Studio 2013中):

error C2027: use of undefined type 'Plugin'
error C2338: can't delete an incomplete type
warning C4150: deletion of pointer to incomplete type 'Plugin'; no destructor called

我挖了一下,显然这是由std :: unique_ptr的删除引起的(在它正在运行的类的类定义中找到它自己)。我在某处读到,如果我提供自己的删除器,这个问题就会消失。所以我将PluginPtr重新定义为:

typedef std::unique_ptr<Plugin, PluginDeleter> PluginPtr

(编译)问题确实消失了,但问题是,可以/应该PluginDeleter手动调用~Plugin()(以确保插件(以及PluginPtr可能出现的任何派生对象)指向!)被正确破坏)?我应该在哪里/如何最好地声明/定义它,以便我不会在不完整的类型中遇到同样的问题?

(还是有更好的方法吗?)

PS。现在处理我的源代码,我意识到上面的代码中存在错误。 Type.cpp中的最后一行应该是

    PluginPtr CreateInstance() { return (_createInstance_Handler)(); }

1 个答案:

答案 0 :(得分:2)

std::unique_ptr的删除者应该删除该对象,也就是说将其销毁(正如你可以认为的那样),然后释放所需的内存。

如果您的自定义删除器使用delete运算符,则您不必手动调用析构函数:

  

delete是一个具有非常特定行为的运算符:表达式   使用delete运算符,首先调用适当的析构函数(for   类类型),然后调用函数运算符delete(即,这   功能)释放存储。

如果使用静态分配的内存或静态分配的内存或内存中的placement-new创建指针,则在应用程序退出之前不会释放(例如),那么就不应该调用delete运算符,但你仍然需要销毁对象,因此你必须调用对象的析构函数。