情境:
我正在使用旧C ++库中的一个方法,它返回一个指向SomeClass
的原始指针,其中SomeClass
是库头中的导出类,如SomeClass.h
以下是我正在使用的LibraryMethod
的签名:
SomeClass* LibraryMethod();
我无权更改图书馆。我只使用二进制&公共标题,这是一个典型的场景。
我不想在我的代码中使用原始指针。因此,我在使用库API的代码中有shared pointer到SomeClass
。
std::shared_ptr<SomeClass> some_class;
我这样初始化以避免将原始指针存储到SomeClass
some_class = (std::shared_ptr<SomeClass>)LibraryMethod();
这基本上有效但我想了解这里的细节
问题:
以上是正确的技术吗?
我在这里造成泄漏吗?
有没有更好的技术来处理这种情况?
答案 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 talk或this one @8:40。如果您的代码中有一个消耗并拥有该资源的实体,您可以考虑使用std::unique_ptr。
如果LibraryMethod
可能会抛出异常,则必须相应地处理此情况。