如何传递unique_ptr <T>代替raw*output*指针参数?

BTo*_*TKD 8 c++ unique-ptr c++11

我在外部库中有一个预先存在的函数,看起来像这样;

bool CreateTheThing(MyThing *& pOut);
Run Code Online (Sandbox Code Playgroud)

简而言之; 我给它一个原始指针(通过引用),该函数分配内存并将我的指针分配给新分配的对象.当函数返回时,它是我的责任,以释放内存,当我完成了.

显然,我想把这个结果存入一个unique_ptr<MyThing>,并避免使用手册delete.

可以创建一个临时的原始指针,用于API调用,并将其传递给构造函数unique_ptr;

MyThing* tempPtr;
CreateTheThing(tempPtr);
unique_ptr<MyThing> realPtr = unique_ptr<MyThing>(tempPtr);
Run Code Online (Sandbox Code Playgroud)

有比这更直接的方法吗?一个不需要临时原始指针的?理想情况下,会有一种方法unique_ptr以一种可以直接使用该CreateTheThing方法的方式公开其内部指针?

unique_ptr<T>::get()据我所知,不允许这样做.它返回的指针不是对内部使用指针的引用.

πάν*_*ῥεῖ 9

有比这更直接的方法吗?一个不需要临时原始指针的?

不,没有.

理想情况下,会有一个unique_ptr方法以一种可以直接使用CreateTheThing方法的方式公开其内部指针? unique_ptr::get()据我所知,不允许这样做.

你的知识是正确的.那会破坏整个目的std::unique_ptr,因此unique_ptr::get()是一个const函数,指针由值返回.

但是与构造函数示例类似,您始终可以使用std::unique_ptr::reset()传递外部分配的指针.

另请注意:如果第三方API要求您使用释放内存free(),则可能需要为其提供特殊的删除功能std::unique_ptr.

  • nitpick:`unique_ptr :: get()`返回指针*by-value*是你无法改变通过它存储的内容的原因. (2认同)

Rei*_*ica 9

您可以通过编写多行代码来保存一行代码(可能多次):

class Wrapper
{
  std::unique_ptr<MyThing> &u;
  MyThing *p;

public:
  Wrapper(std::unique_ptr<MyThing> &u) : u(u), p() {}

  operator MyThing* & ()
  { return p; }

  ~Wrapper()
  { u.reset(p); }
};
Run Code Online (Sandbox Code Playgroud)

用法:

std::unique_ptr<MyThing> u;
CreateTheThing(Wrapper(u));
Run Code Online (Sandbox Code Playgroud)

  • @BTownTKD加上一个`template <class T> make_out_ptr_adapter()`用于类型推导,当然. (2认同)

Mic*_*Roy 5

如果您经常使用该函数,则可以将转换放入函数中。

最好是更改 API,但这也可以。

inline std::unique_ptr<MyThing> CreateTheThing()
{
  MyThing* p;
  if (CreateTheThing(p))
  {
    return std::unique_ptr<MyThing>(p);
  }
  return std::unique_ptr<MyThing>();
}
Run Code Online (Sandbox Code Playgroud)

您还可以使此重载使重构更容易:

inline bool CreateTheThing(std::unique_ptr<MyThing>& ptr)
{
    try 
    {
        MyThing* p;
        if (CreateTheThing(p))
            ptr = std::unique_ptr<MyThing>(p);
        else
            return false;
    }
    catch (std::bad_alloc&)
    {
        return false;
    }
    return true;
}
Run Code Online (Sandbox Code Playgroud)