调用 delete 的自定义 unique_ptr 删除器有什么用?

What is the use of a custom unique_ptr deleter that calls delete?

NVidia's TensorRT library 提供的 C++ 示例中,有一个名为 common.h 的文件,其中包含整个示例中使用的结构定义。

除其他外,该文件包含 the following definitions:

struct InferDeleter
{
    template <typename T>
    void operator()(T* obj) const
    {
        delete obj;
    }
};

template <typename T>
using SampleUniquePtr = std::unique_ptr<T, InferDeleter>;

SampleUniquePtr 别名在整个代码示例中用于包装各种指向由某些函数返回的接口 类 的指针,例如SampleUniquePtr<INetworkDefinition>(builder->createNetworkV2(0));

我的问题是,std::unique_ptrSampleUniquePtr 在哪些实际方面不同? SampleUniquePtr 的行为几乎是我对 std::unique_ptr 的期望,至少现在是这样。难道是为了兼容老版本的C++?

该示例看起来毫无意义,因为这正是我希望默认删除程序执行的操作。

但也许这样更好(未经测试):

#include <vector>
struct VectorDeleter
{
    template <typename T>
    void operator()(std::vector<T*> *v) const
    {
        for(auto p : *v) delete p;
        delete v;
    }
};

template <typename V>
using UniquePtrVector = std::unique_ptr<V, VectorDeleter>;

当你有一个指针向量(例如指向多态类)时,你必须在删除向量时删除向量指向的对象。 VectorDeleter 在矢量本身被删除之前执行此操作。

我没有时间浏览整个链接库,所以我在这方面有可能是错的。

但是,您看到的可能是一个 默认 实现,用作不需要特殊处理的任何类型的后备。

库实现者总是可以选择在他们处理的类型确实需要特殊处理的情况下专门化此函数,这对于 Nvidia 制作的库来说可能很常见(因此可能意味着与 GPU 交互)。

class GPUResource {
//...
~GPUResource() noexcept {} //Does NOT perform the special handling, for whatever library-specific reason
};

template<>
void InferDeleter::operator()<GPUResource>(GPUResource * obj) {
    performSpecialCleanupOnGPUResource(obj->handle);
    delete obj;
}

在实践中,这种东西总是闻起来像 anti-pattern(你 确定,库实现者,你不能在析构函数中进行清理这个对象的??)但是如果他们有充分的理由像这样分离逻辑,他们定义的方式 InferDeleter 允许他们这种灵活性。

history我看是有一段时间了

template <typename T>
void InferDeleter::operator()(T* obj) const
{
    if (obj)
    {
        obj->destroy();
    }
}

然后他们宣布 destroy() 方法已弃用:

  • Destructors for classes with destroy() methods were previously protected. They are now public, enabling use of smart pointers for these classes. The destroy() methods are deprecated.

虽然它已被弃用,但仍未删除,旧的 ABI InferDeleter 应该保留,以便与旧的 TensorRT 链接的应用程序向后兼容。因此他们最近开始使用

template <typename T>
void InferDeleter::operator()(T* obj) const
{
    delete obj;
}

不删除 struct InferDeleterusing SampleUniquePtr = std::unique_ptr<T, InferDeleter>。但它可能会在未来被删除。当他们删除 struct InferDeleter 并更改 using SampleUniquePtr = std::unique_ptr<T> 时,这将使 TensorRT 库与旧软件不兼容。