std :: unique_ptr,自定义删除和类型更改

时间:2017-01-01 11:53:16

标签: c++ c++11 stl smart-pointers unique-ptr

我想将unique_ptr与我的删除器一起使用。 我希望我的unique_ptr与我的删除器完全兼容unique_ptr与默认删除器。

我这样做了:

template <typename T>
struct QObjectDeleteLaterDeletor :
        public std::default_delete<T>
{
    void operator()(T *p)
    {
        p->deleteLater();
    }
};

template <typename T, class... Args>
std::unique_ptr<T> qtMakeUniqueSpecial(Args&&... args)
{
    return std::unique_ptr<T>(
                new T(std::forward<Args>(args)...),
                QObjectDeleteLaterDeletor<T>());
}

这会编译,但不起作用。我的自定义删除器被忽略,默认使用默认删除器,就像我根本没有指定它一样。

我需要所有这些能够做到这样的事情:

auto ptr1 = qtMakeUniqueSpecial<MyObject>();
std::unique_ptr<MyObject> ptr2;
ptr2 = std::move(ptr1);

请注意,现在即使是ptr1.reset()也会导致调用标准删除器,而不是我的。

甚至可能吗?

2 个答案:

答案 0 :(得分:2)

您需要指定QObjectDeleteLaterDeletor作为模板参数;否则,std::default_delete将用作删除器,它将从QObjectDeleteLaterDeletor进行切片复制。

template <typename T, class... Args>
std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> qtMakeUniqueSpecial(Args&&... args)
{
    return std::unique_ptr<T, QObjectDeleteLaterDeletor<T>> (
                new T(std::forward<Args>(args)...),
                QObjectDeleteLaterDeletor<T>());
}

请注意,您将ptr2声明为std::unique_ptr<MyObject>,然后ptr2会通过std::default_delete销毁指针。如果您声明其类型符合ptr1 auto ptr2 = std::move(ptr1);,那么它就没问题了。

答案 1 :(得分:1)

您正在尝试使用

namespace std {
  template<typename T, typename Deleter = default_delete<T> >
  class unique_ptr;
}

有第二个模板参数Deleter。如果未指定,则默认为std::default_delete<T>。你的代码

std::unique_ptr<T>(new T(std::forward<Args>(args)...),
                   QObjectDeleteLaterDeletor<T>());

const std::default_delete<T>&传递给constructor of std::unique_ptr<T>,因为这是构造函数所期望的。在销毁(或致电会员reset())后,这将被调用。

请注意std::shared_ptr的行为是不同的:删除器没有第二个模板参数,尽管可以在构造时提供自定义删除器(这需要通过类型擦除来存储,这可以避免使用std::unique_ptr)。