将 std::make_unique 与自定义删除器一起使用

Using std::make_unique with a custom deleter

本文关键字:删除 一起 自定义 std make unique      更新时间:2023-10-16

在将std::unique_ptr与自定义删除器一起使用时,我希望使用std::make_unique而不是原始的新。 我正在使用VC++2013。 在我看来,如果您使用的是自定义删除器,则无法使用std::unique_ptr。 是我错过了什么,还是真的是这样?


附加信息:

我正在使用std::unique_ptr<HANDLE, custom_deleter>来持有打开的COM端口的Windows句柄。

我可以为此编写一个自定义 RAII 类,这不会非常困难,但我看到使用 std::unique_ptr 会有多难/困难/糟糕。

make_unique的全部

意义在于封装"使用 new给定的构造函数参数创建T并使用delete来销毁它"的概念。

如果你想要一个自定义删除器,你还必须指定如何创建对象,然后使用放置 maker 函数就没有什么好处了。

我在这篇文章中为某些独特的资源句柄编写了一些自定义制作者函数的示例。

这是一种使用调用自定义自由函数的自定义删除器将 c 样式内存管理包装到std::unique_ptr中的方法。这有一个类似于 std::make_unique LIVE 的 make 函数助手:

#include <iostream>
#include <functional>
#include <memory>
// Some C style code that has some custom free function ptr...
extern "C" {
struct ABC { };
enum free_type_e {
    FREE_ALL,
    FREE_SOME
};
typedef void (free_f)(enum free_type_e free_type, void *ptr);
struct some_c_ops { free_f* free_op; };
void MY_free(enum free_type_e free_type, void *ptr)
{
    printf("%s:%d ptr=%ldn", __func__, __LINE__, (long)ptr);
    (void)free_type;
    free(ptr);
}
}; // extern "C"
template<typename T>
using c_unique_ptr = std::unique_ptr<T,std::function<void(T*)>>;
template <typename T>
c_unique_ptr<T> make_c_unique(some_c_ops* op, free_type_e free_type)
{
    return c_unique_ptr<T>(static_cast<T*>(calloc(1, sizeof(T))),
                           std::bind(op->free_op, free_type, std::placeholders::_1));
}
void foo(c_unique_ptr<ABC> ptr)
{
    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) <<     std::endl;
}
int main()
{
    some_c_ops ops = { MY_free };
    c_unique_ptr<ABC> ptr = make_c_unique<ABC>(&ops, FREE_ALL);
    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
    foo(std::move(ptr));
    std::cout << __func__ << ":" << __LINE__
        << " ptr=" << reinterpret_cast<size_t>(ptr.get()) << std::endl;
}

可能的输出:

main:48 ptr=50511440
foo:40 ptr=50511440
MY_free:20 ptr=50511440
main:53 ptr=0

我所知,C++11标准中没有make_unique功能。看

  • 为什么C++11有"make_shared"而不是"make_unique"
  • make_unique和完美的转发

因此,我假设make_unique是至少未包含在标准中的Microsoft实现。

但是,尽管如此,您仍然可以将自定义删除程序与 unique_ptr .使用 unique_ptr 时,必须将删除器的类型指定为第二个模板参数,然后将适当的对象传递给构造函数。