将从方法返回的原始指针存储到智能指针中

时间:2017-10-10 17:18:02

标签: c++ c++11 c++14

情境:
我正在使用旧C ++库中的一个方法,它返回一个指向SomeClass的原始指针,其中SomeClass是库头中的导出类,如SomeClass.h

以下是我正在使用的LibraryMethod的签名:

SomeClass* LibraryMethod();

我无权更改图书馆。我只使用二进制&公共标题,这是一个典型的场景。

我不想在我的代码中使用原始指针。因此,我在使用库API的代码中有shared pointerSomeClass

std::shared_ptr<SomeClass> some_class;

我这样初始化以避免将原始指针存储到SomeClass

some_class = (std::shared_ptr<SomeClass>)LibraryMethod();

这基本上有效但我想了解这里的细节

问题:
以上是正确的技术吗? 我在这里造成泄漏吗? 有没有更好的技术来处理这种情况?

4 个答案:

答案 0 :(得分:6)

你应该把它称为

auto some_class = std::shared_ptr<SomeClass>(LibraryMethod());

这假设LibraryMethod正在分配指针并为您提供内存的所有权。

按照目前的编写,你试图使用C风格的强制转换(可能导致reinterpret_cast)将原始指针强制转换为std::shared_ptr。相反,您希望使用返回的原始指针construct a std::shared_ptr

答案 1 :(得分:3)

代码有效,但它很丑陋而且很脆弱。为什么将漂亮的现代C ++(智能指针)与C风格的演员表混淆和危险的东西混合在一起?你打电话给array([[ 2., 3., 4.]]) 时要好得多:

reset

以上假设(正如您的问题似乎表明)您已经在某处宣布some_class.reset(LibraryMethod()); 并想要重新分配它。如果您在调用std::shared_ptr<SomeClass> some_class;之前创建some_class,则直接初始化它会好得多:

LibraryMethod

这相当于CoryKramer's answer

但请注意,所有这些代码都隐藏了一个很大的假设:std::shared_ptr<SomeClass> some_class(LibraryMethod()); 返回一个指向通过LibraryMethod动态分配的内存的指针,并且其调用者负责通过调用最终释放该内存new

答案 2 :(得分:3)

在您的情况下,正确的方法应该是使用shared_ptr构造函数:

std::shared_ptr<SomeClass> sPtr(LibraryMethod());

但是首先你应该知道LibraryMethod()返回的指针真正意味着什么,大多数库返回原始指针只是说&#34;嘿,你可以通过这个指针访问这个对象,但要注意,我仍然负责管理它,所以......不要删除它! &#34;

如果你确定在那次通话后你负责管理它,那么好的,你可以放心使用shared_ptr。

答案 3 :(得分:2)

  

以上是正确的技术吗?

是的,假设LibraryMethod使用new分配资源,并且库用户负责删除它。使用智能指针包装原始指针广泛用于遗留库。

  

我在这里造成泄漏吗?

不,如果你做得对。我同意其他答案,但你也可以这样做:

std::shared_ptr<SomeClass> some_class(LibraryMethod());
  

有没有更好的技术来处理这种情况?

要仔细考虑的一件事是LibraryMethod分配的资源的所有权。一些人认为shared_ptr是邪恶的,因为它只是一种更好的方式来引入一个难以跟踪的依赖关系的全局。例如,请参阅Sean Parent的this talkthis one @8:40。如果您的代码中有一个消耗并拥有该资源的实体,您可以考虑使用std::unique_ptr

如果LibraryMethod可能会抛出异常,则必须相应地处理此情况。