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

How to use smart pointer in this situation

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

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

现在 API 可能 return 出错或成功通过,但在这两种情况下我都想删除对象,一种方法是在错误退出和正常退出期间编写删除语句.

但是我如何为这些指针使用智能指针呢? 我所说的智能指针是指 unique_ptr、shared_ptr 等,无论哪个都可以工作!

谢谢!

您可以为 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 或为您的结构编写一个包装器 class。

我假设您无法修改 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);

您甚至可以通过 SOME_STRUCT_plus_plusSOME_STRUCT 派生而不是聚合它来 "wrap" 它,这样您就可以直接访问成员而无需通过 s.同时,如果有人将 SOME_STRUCT_plus_plus* 转换为 SOME_STRUCT*,然后在其上调用 delete,则可能会导致内存泄漏。

这里好像可以全部入栈:

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