std::unique_ptr 带有自定义删除器,用于包装 malloc 指针

std::unique_ptr with custom deleter for wrapping a malloc pointer

提问人:D.J. Elkind 提问时间:6/12/2023 最后编辑:Jan SchultkeD.J. Elkind 更新时间:6/12/2023 访问量:260

问:

我有一个 C 库函数:

uint8_t* c_func();

这要么返回分配了 的有效指针,要么返回错误。我想把它包装成如下:uint8_tmalloc()NULLstd::unique_ptr()

struct FreeDeleter {
  void operator()(void *p) const {
    std::free(p);
  }
};

template <typename T>
using unique_fptr = std::unique_ptr<T, FreeDeleter>;

std::free()如果传递给它的指针是 ,则不执行任何操作,因此这应该按预期工作。NULL

这种设计是否正确,它是否遵循在 C++ 中包装原始指针的最佳实践?

C++ malloc 智能指针

评论

0赞 D.J. Elkind 6/12/2023
@JeJo哈哈C++进化得如此之快......仍然被很多用户认为是“新的”。std::unique_ptr
6赞 Miles Budnek 6/12/2023
@JeJo/在这里并没有真正的用处。它们用于函数通过 out 参数(即 )返回时,这在这里不适用。当您使用它们时,您仍然必须拥有一个;您只是不需要中间原始指针。由于 OP 的 C 函数实际上返回一个指针,因此只需 a 即可。std::out_ptr_tstd::inout_ptr_tvoid c_func(foo** ret)std::unique_ptrstd::unique_ptr
0赞 Homer512 6/12/2023
代码很好。我一直在做同样的事情,包括删除者调用的类似事情。对于这种特殊情况,您可以将其限制为 std::is_trivially_destructible 类型,但这只是一个噱头FILE*fclose
0赞 D.J. Elkind 6/12/2023
@Homer512 如果你知道它是,你为什么不直接使用这样的东西?FILE*iostream
0赞 Homer512 6/12/2023
与 C 库的互操作性以及调用 filenofdopen 以使用 POSIX 例程的能力。我还认为更易于阅读并且可能更快(更少的互斥锁/解锁周期)fprintf

答:

4赞 Sebastian Redl 6/12/2023 #1

是的,这是最佳做法。

我会更进一步,将 C 函数包装在一个函数中,该函数会立即将结果包装在unique_ptr中,这样您就不会忘记这样做。

但是,需要注意的是!如果 C 函数位于 Windows 上的共享库中,则它可能使用不同的堆,因此在主程序中使用 free 将无效。但是,除非库提供自己的自定义免费函数,否则您对此无能为力,在这种情况下,您无论如何都应该使用它。

评论

1赞 Eljay 6/12/2023
警告是正确的!我希望我能给超过+1。
0赞 D.J. Elkind 6/13/2023
由于我通常不在 Windows 上编程,所以我不知道这一点。只是出于好奇,这是否意味着在 Windows 上我的程序不能由共享库函数编辑内存?free()malloc()
0赞 Sebastian Redl 6/13/2023
是的,这是一个潜在的问题。这取决于确切的设置。从理论上讲,如果 EXE 和 DLL 都动态链接到相同版本的 CRT DLL,则可以跨模块边界进行 malloc/free。但是,如果静态链接或链接到其他版本,则代码会中断。因为我们谈论的是 DLL,这意味着当替换 DLL 时,它甚至可能在不重新编译 EXE 的情况下中断!因此,最好不要冒险并采取相关的预防措施。