我想在以下情况下使用智能指针:
SOME_STRUCT* ptr = new SOME_STRUCT;
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr);
现在API可以返回错误或成功传递,但在这两种情况下我想删除对象,一种方法是在错误退出期间和正常退出期间写入delete语句。
但是我怎样才能为这些指针使用智能指针? 通过智能指针,我的意思是unique_ptr,shared_ptr等,无论哪个都可以工作!
谢谢!
答案 0 :(得分:3)
您可以为unique_ptr
编写自定义删除工具。
struct my_deleter {
void operator()(SOME_STURCT* ptr) const {
delete[] ptr->SOME_MEMBER;
delete ptr;
}
};
using my_ptr = std::unique_ptr<SOME_STRUCT, my_deleter>;
我建议将new SOME_STRUCT;
更改为new SOME_STRUCT{};
,默认情况下将SOME_MEMBER
初始化为nullptr
。
我对这个解决方案并不是100%满意,所以也许可以查看scope_guard
或为你的struct编写一个包装类。
答案 1 :(得分:2)
我假设您无法修改SMOE_STRUCT
以向其添加析构函数。这为您提供了两个选项:自定义删除和封装。
首先,您可以创建一个自定义删除器,以便与std::unique_ptr
一起使用:
struct SOME_STRUCT_Deleter
{
void operator() (SOME_STRUCT *p) const
{
delete[] p->SOME_MEMBER;
delete p;
}
};
std::unique_ptr<SOME_STRUCT, SOME_STRUCT_Deleter> ptr{new SOME_STRUCT};
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr.get());
如果您发现这一点,与您问题中描述的情况不同,共享所有权比排除所有权更适合您,您也可以将删除器与shared_ptr
一起使用,如下所示:
std::shared_ptr<SOME_STRUCT> ptr{new SOME_STRUCT, SOME_STRUCT_Deleter{}};
ptr->SOME_MEMBER = new BYTE[100];
CallSomeAPI(ptr.get());
第二个选项,我认为更可取的是包裹SOME_STRUCT
:
struct SOME_STRUCT_plus_plus
{
SOME_STRUCT s;
~SOME_STRUCT_plus_plus()
{
delete[] s.SOME_MEMBER;
}
SOME_STRUCT_plus_plus()
{
s.SOME_MEMBER = new BYTE[100];
}
};
std::unique_ptr<SOME_STRUCT_plus_plus> ptr{new SOME_STRUCT_plus_plus};
CallSomeAPI(&ptr->s);
你甚至可以&#34;包裹&#34;通过使SOME_STRUCT_plus_plus
派生自SOME_STRUCT
而不是汇总它,这可以让您直接访问成员而无需通过s
。同时,如果有人将SOME_STRUCT_plus_plus*
转换为SOME_STRUCT*
,然后在其上调用delete
,则可能会导致内存泄漏。
答案 2 :(得分:1)
在这里,似乎所有人都可以在堆栈中:
SOME_STRUCT ptr; // or auto ptr = std::make_unique<SOME_STRUCT>();
BYTE bytes[100]; // or std::vector<BYTE> bytes(100);
ptr.SOME_MEMBER = bytes; // or ptr->SOME_MEMBER = bytes.data();
CallSomeAPI(&ptr); // or CallSomeAPI(ptr.get());