C++ 如何通过唯一ptr<;T>;替代原始*输出*指针参数?

C++ 如何通过唯一ptr<;T>;替代原始*输出*指针参数?,c++,c++11,unique-ptr,C++,C++11,Unique Ptr,我在外部库中有一个预先存在的函数,如下所示 bool CreateTheThing(MyThing *& pOut); 简言之;我给它一个原始指针(通过引用),函数分配内存并将我的指针分配给新分配的对象。当函数返回时,我有责任在完成后释放内存 显然,我希望将此结果存储到唯一的\u ptr,并避免手动删除 我可以创建一个用于API调用的临时原始指针,并将其传递到unique_ptr的构造函数中 MyThing* tempPtr; CreateTheThing(tempPtr); uniq

我在外部库中有一个预先存在的函数,如下所示

bool CreateTheThing(MyThing *& pOut);
简言之;我给它一个原始指针(通过引用),函数分配内存并将我的指针分配给新分配的对象。当函数返回时,我有责任在完成后释放内存

显然,我希望将此结果存储到
唯一的\u ptr
,并避免手动
删除

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

MyThing* tempPtr;
CreateTheThing(tempPtr);
unique_ptr<MyThing> realPtr = unique_ptr<MyThing>(tempPtr);
MyThing*temptr;
创建内容(tempPtr);
unique_ptr realPtr=unique_ptr(temptr);
还有比这更直接的方法吗?不需要临时原始指针的指针?理想情况下,会有一个
unique_ptr
方法,它以一种可以直接与
CreateTheThing
方法一起工作的方式公开其内部指针


据我所知,
unique\u ptr::get()
不允许这样做。它返回的指针不是对内部使用的指针的引用。

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

最好是更改API,但这也可以起作用

inline std::unique_ptr<MyThing> CreateTheThing()
{
  MyThing* p;
  if (CreateTheThing(p))
  {
    return std::unique_ptr<MyThing>(p);
  }
  return std::unique_ptr<MyThing>();
}
inline std::unique_ptr CreateTheThing()
{
神话*p;
如果(创建内容(p))
{
返回std::unique_ptr(p);
}
返回std::unique_ptr();
}
您还可以使此重载使重构更加容易:

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;
}
inline bool创建内容(std::unique\u ptr&ptr)
{
尝试
{
神话*p;
如果(创建内容(p))
ptr=std::unique_ptr(p);
其他的
返回false;
}
捕获(标准::错误分配&)
{
返回false;
}
返回true;
}
还有比这更直接的方法吗?不需要临时原始指针的指针

不,没有

理想情况下,会有一个unique_ptr方法,它以一种可以直接与createThing方法一起工作的方式公开其内部指针<据我所知,code>unique\u ptr::get()不允许这样做

你的知识是正确的。这将破坏
std::unique\u ptr
的全部功能,因此
unique\u ptr::get()
是一个
const
函数,指针由值返回

无论与构造函数示例多么相似,您始终可以使用
std::unique\u ptr::reset()
传递外部分配的指针


另请注意:如果第三方API要求您使用
free()
释放内存,您可能需要为
std::unique\u ptr

提供一个特殊的删除函数,您可以通过一次写入多行代码来保存一行代码(可能多次):

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); }
};
类包装器
{
std::独特的ptr&u;
神话*p;
公众:
包装器(std::unique_ptr&u):u(u),p(){}
运算符神话*&()
{返回p;}
~Wrapper()
{u.reset(p);}
};
用法:

std::unique_ptr<MyThing> u;
CreateTheThing(Wrapper(u));
std::unique_ptr u;
创建内容(包装器(u));

库是否要求您使用
free()
解除分配?有没有理由它不只是返回指针?啊,太糟糕了。外部库迫使您编写愚蠢的代码。您可以将realPtr行缩短为
unique\u ptr realPtr(temptr)是,或!:
auto realPtr=unique_ptr(temptr)
CreateTheThing()
是从外部库调用的函数。我怀疑OP能简单地改变它,这是正确的。为了清楚起见,我编辑了这个问题。我希望避免更改外部库中的旧API。IMO这是最好的答案,因为您可以使用它通过将旧的
API
隐藏在新的包装器函数API后面,迫使应用程序的其余部分使用新方法。然后你就知道没有人会因为拥有原始指针而迷失方向。这个解决方案并没有隐藏原始api。它提供了一个覆盖。无法隐藏全局函数。它不是虚拟函数,因此不会“覆盖”任何内容。但是是的,它是一个重载,不会隐藏或以其他方式干扰原始
CreateTheThing()
。我不知道@Galik是什么意思;也许他们可以澄清。清楚、简洁、明确的回答。非常感谢你!吹毛求疵:
unique\u ptr::get()
按值返回指针是您无法更改通过它存储的内容的原因。@Caleth Better?整洁<代码>模板类输出ptr适配器
@BTownTKD加上一个用于类型推断的
模板make\u ptr\u adapter()
,当然。p应该用nullptr初始化,以确保异常安全。@CAF
p
是值初始化的(注意ctor mem初始化器列表中的
p()
),这意味着它将是一个空指针。