我可以重新绑定unique_ptr的删除器类型吗?

时间:2016-05-21 09:17:38

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

在使用unique_ptr时遇到了一些问题并试图阅读来源,但会出现更多问题。

Deleter中的模板参数unique_ptr<class Tp, class Deleter = default_delete<Tp>>是一个模板以外的类,所以我想知道它是否使用了allocator::rebind(讨论发现here)等一些技巧。但不,它必须有一个确切的operator()(pointer)超载。

所以我转向STL源代码(在Ubuntu 14.04 gcc 4.8中)并发现嵌套的_Pointer类是为某些类型特征定义的,但绝对与将Deleter类型重新绑定为无关与指针类型兼容的东西。

// /usr/include/c++/4.8/bits/unique_ptr.h:112
class _Pointer
{
    template<typename _Up>
    static typename _Up::pointer __test(typename _Up::pointer*);

    template<typename _Up>
    static _Tp* __test(...);

    // _Dp is the Deleter type
    typedef typename remove_reference<_Dp>::type _Del;
public:
    typedef decltype(__test<_Del>(0)) type;
};

// /usr/include/c++/4.8/bits/unique_ptr.h:130
// adopt the pointer type provided by the _Pointer
typedef typename _Pointer::type   pointer;

我不知道该课程应该做什么,但似乎Tp参数可以被覆盖。为了测试它,我制作了一些像这样的奇怪代码

struct MyDeleter {
    // in the deleter type, define the pointer as pointer to int
    typedef int* pointer;

    void operator()(pointer p)
    {
        delete p;
    }
};

int main()
{
    // this won't compile!
    std::unique_ptr<double, MyDeleter> p(new double(0));

    // this type is equivalent to std::unique_ptr<int, MyDeleter>
    std::unique_ptr<double, MyDeleter> p(new int(0));
    return 0;
}

我完全糊涂了。有人会解释

  • 是否有任何方法可以重新绑定unique_ptr的删除器类型?
  • 为什么有这样的机制来覆盖指针类型?这是在标准中说明的还是只是一个&#34;特征&#34;在gcc实现中?

1 个答案:

答案 0 :(得分:1)

规则说如果MyDeleter具有嵌套类型pointer,则使用该类型。否则std::unique_ptr<double, MyDeleter>将使用由第一个参数组成的double*

您存储的指针必须与unique_ptr的结果指针类型匹配,否则最终删除将是UB。

因此,在std::unique_ptr<double, MyDeleter> p(new double(0));的第一种情况下,当删除者期望double*时,您会尝试存储int*。这将永远不会奏效,因此编译器捕获它是件好事。