如何将unique_ptr与 c 库中分配的数据一起使用
How to use unique_ptr with data allocated within a c library?
我在 c++ 中,我正在围绕 c 库编写一个包装器。我正在使用的 c 库函数将类型"LDAPMessage **"作为参数,它将在函数中为您分配内存。正常用法如下所示:
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
现在我想在这种情况下使用unique_ptr,带有自定义删除器。假设我的删除器"LDAPMessageDeleter"存在并在下面工作。
unique_ptr<LDAPMessage*, LDAPMessageDeleter> msg_ptr(new LDAPMessage*);
c_lib_function(msg_ptr.get());
虽然这为我编译,但我遇到了一个 seg 错误。这段代码会不会有问题?这是unique_ptr的正确用法吗?
可能更容易,例如
LDAPMessage* msg;
c_lib_function(&msg);
// Now we have out pointer (hopefully)
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> msg_ptr(msg);
当然,LDAPMessageDeleter
必须调用适当的函数来释放内存(例如 free
是内存分配了 malloc
)。
您在问题中显示的代码的问题在于,您尝试创建指向指针的指针,但不要使该第一级指针实际指向任何地方。
你在代码中有效地执行的是:
LDAPMessage** msg;
c_lib_function(msg);
C 库中发生的事情是指针是"通过引用"传递的。由于 C 实际上没有适当的引用,因此它可以通过传递指针来模拟。传递对指针的"引用"是通过使用地址运算符传递指针的地址(然后成为指向指针的指针)来完成的。
SO 聊天中的某个人像这样开发了有价值的代码,我再也找不到了:
//ptrptr magic
#include <memory>
template<class T, class deleter>
class ptrptr_type {
public:
ptrptr_type(std::unique_ptr<T, deleter>& ptr)
: uptr(&ptr), tptr(ptr.get()) {}
~ptrptr_type() {if (uptr->get()!=tptr) uptr->reset(tptr);}
operator T**() {return &tptr;}
private:
std::unique_ptr<T, deleter>* uptr;
T* tptr;
};
template<class T, class D>
ptrptr_type<T,D> ptrptr(std::unique_ptr<T, D>& ptr) { return {ptr};}
这个ptrptr
的用法非常简单:
std::unique_ptr<LDAPMessage, LDAPMessageDeleter> my_ptr; //can be null or initialized, whichever
c_lib_function(ptrptr(my_ptr)); //use ptrptr(my_ptr) whenever you need a T**
就是这样。 真的很简单。 http://coliru.stacked-crooked.com/a/644ed001ffd547ae
发生的情况是ptrptr(my_ptr)
堆栈上创建一个临时ptrptr_type
,该从unique_ptr
中获取指针。 然后,ptrptr
公开指向其内部指针的指针,C 函数可以自由修改该指针。 之后,临时ptrptr_type
被销毁,其析构函数将指针的新值放回原始unique_ptr
。
这不是指针到指针的正确用法。该函数获取指向未初始化指针的指针并填充它。在您的第一个示例中,这是一个局部变量。如果您希望它由 unique_ptr
管理,它应该仍然是一个本地的,只是包含在 unique_ptr
对象中。
LDAPMessage * msg;
c_lib_function(&msg); // allocates the memory for me
std::unique_ptr< LDAPMessage, LDAPMessageDeleter > // This type contains a ptr
msg_ptr( msg ); // transfer ownership to C++
LDAPMessageDeleter
应该收到一个LDAPMessage *
,必要时传递给库释放,否则传递给free()
。
- 拥有映射的现代方法,该映射可以指向或引用已在堆栈上分配的不同类型的数据
- 动态分配的聊天数组打印缺失的数据和空
- 基于浅树的数据结构的内存分配器,用于频繁分配和解除分配
- C++,在对象内分配多个数据时,堆栈分配是否更有效? 在下面的程序中,类A_Heap的效率会更低吗?
- 我想知道我是否可以将一个类分配给特定的成员数据并创建该类的实例
- 使用 delete [] 运算符取消分配类中数据成员的内存
- 如何在C 中的派生类中分配数据成员数组
- 动态分配数据类型C++
- 映射资源并在direct3d11中分配数据
- 正在为堆上的priority_queue分配数据
- C++删除堆分配数据的二进制数组-它会全部删除吗?关于删除,我应该知道些什么
- 在窗口中的特定地址分配数据
- 使用SetData()分配数据后,cvReleaseImage()出现分段错误
- c++中栈分配数据的生命周期
- 从OpenCV中用户分配数据的Mat构造函数
- 我如何知道指针是否已通过"新建"分配数据?
- 在For循环中声明多个变量,然后为这些变量分配数据
- 查找已分配数据的未执行位
- std::vector::assign-重新分配数据
- 如果我在使用新的和结束的程序分配数据后没有调用删除运算符,会发生什么情况?