在这种情况下如何使用智能指针

时间:2015-05-15 08:43:35

标签: c++ smart-pointers

我想在以下情况下使用智能指针:

   SOME_STRUCT* ptr = new SOME_STRUCT;
   ptr->SOME_MEMBER = new BYTE[100];
   CallSomeAPI(ptr);

现在API可以返回错误或成功传递,但在这两种情况下我想删除对象,一种方法是在错误退出期间和正常退出期间写入delete语句。

但是我怎样才能为这些指针使用智能指针? 通过智能指针,我的意思是unique_ptr,shared_ptr等,无论哪个都可以工作!

谢谢!

3 个答案:

答案 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());