如何为 unique_ptr 管理的数组编写自定义删除器?

How can I write a custom deleter for an array managed by an unique_ptr?

我正在尝试找到一种方法来为模板化 C++ class 中的 unique_ptr 管理的 C 数组编写自定义删除器。我故意让删除器什么也不做,从而使 class 内存泄漏。在完整的 class 中,一些构造函数分配内存,而另一些则不分配 - 而是它们使用来自数据流的原始字节缓冲区中的内存。

这是我试过的:

template <class T> class Matrix
{
    private:
    int _size;
    std::unique_ptr<T[]> _array;

    public:
    Matrix(int size, void* data) : _size(size)
                                 , _array(NULL, [](T[]* p){})
    {
        _array.reset((T*)data);
    }
};

代码编译不通过,报错信息为:

In file included from /tmp/test/test/test.cpp:9:
/tmp/test/test/Matrix.h:22:55: error: expected ')'
                                 , _array(NULL, [](T[]* p){})
                                                      ^
/tmp/test/test/Matrix.h:22:51: note: to match this '('
                                 , _array(NULL, [](T[]* p){})
                                                  ^
1 error generated.

首先,始终创建一个简单的设置来测试事物:

int main() {
    using T = int;

    std::unique_ptr<T[]> _array(NULL, [](T[]* p){});

    return 0;
}

现在解决你的问题:

  • T[]* p 无效,应为 T* p.
  • 您作为删除器传递的 lambda 与用作默认删除器的 std::default_delete<T> 不匹配。所以你必须写std::unique_ptr<T[],std::function<void(T*)>
  • NULL 可能被实现为整数类型,所以你应该使用 nullptr 代替,否则 gcc 不会编译你的代码(因为 c++11 你,一般来说,应该使用 nullptr 而不是 NULL).

所以把所有东西放在一起你会得到:

int main() {
    using T = int;

    std::unique_ptr<T[],std::function<void(T[])>> _array(nullptr, [](T* p){});

    return 0;
}

删除器是std::unique_ptr的模板参数。默认情况下它是 std::default_delete,但您可以指定不同的内容,例如

template <typename T>
struct NonDeleter
{
    void operator()(T*) { /* nothing */ }
};

template <typename T>
struct NonDeleter<T[]> : NonDeleter<T> {};

template <class T> class Matrix
{
    private:
    int _size;
    std::unique_ptr<T[], NonDeleter<T[]>> _array;

    public:
    Matrix(int size, void* data) : _size(size)
                                 , _array(static_cast<T*>(data))
    {
    }
};