我什么时候想从原始指针构造一个共享指针 [英] When would I want to construct a shared pointer from a raw pointer
问题描述
感谢 std :: make_shared
,我想知道 std :: shared_ptr
的构造函数是否需要任何值,除非与传统/库代码,例如在存储工厂输出时.
Thanks to std::make_shared
, I wonder, whether the constructor for std::shared_ptr
, which takes a raw pointer has any value except when interfacing with legacy / library code, e.g. when storing the output of a factory.
- 还有其他合法用例吗?
- 避免使用该构造函数是否合理?
- 甚至扩展了对代码的检查,以在每次使用时都警告程序员?
-
shared_ptr< T> :: reset(T *)
是否应使用相同的准则(无论它们是什么)?
- Are there other legitimate use-cases?
- Is it reasonable advice to avoid that constructor?
- Even to the extend of putting code checks for it in place that warn the programmer whenever it is used?
- Should the same guidelines (whatever they are) apply to
shared_ptr<T>::reset(T*)
?
关于代码检查:我知道与遗留代码/库代码的交互非常普遍,因此自动代码检查可能会出现问题,但是到目前为止,在大多数情况下,我还是会使用 unique_ptr
,而且我也是并不是说在 -Wall
弹出的编译器警告,而是关于代码检查期间进行静态代码分析的规则.
Regarding the code checks:
I know that interfacing with legacy / library code is quite common, so automated code checks might be problematic, but in most cases I encountered so far, I'd rather use a unique_ptr
anyway and I'm also not talking about a compiler warning that pops up at -Wall
, but rather about a rule for static code analysis during code review.
我的动机:
说不要使用 std :: shared_ptr< T>(new T(...))
相对容易,总是喜欢使用 std :: make_shared< T>(...)
"(我认为这是正确的建议?).但是我想知道它是否不是一般的设计气味,是否必须从原始指针创建 shared_ptr
,甚至-尤其是-是否不是仅通过 new
,因为该对象首先应该被创建为共享"或唯一"对象.
My motivation:
It is relatively easy to say "Don't use std::shared_ptr<T>(new T(...))
, always prefer std::make_shared<T>(...)
" (Which I believe is correct advise?). But I'm wondering if it isn't a design smell in general, if one has to create a shared_ptr
from a raw pointer, even - or especially - if the object was not just created via new
, because the object should have been created either as a "shared" or "unique" object in the first place.
推荐答案
想到的第一个用例是删除器不是默认的 delete
.
First use case that pops to mind is when the deleter is not the default delete
.
例如在Windows环境中,必须有时使用COM对象,这些对象的释放必须通过 Release
在对象本身上完成.当然可以使用ATL,但并非所有人都希望使用它.
E.g. in a windows environment COM objects must some times be used, the release of these objects must be done on the object itself, via Release
. Sure ATL can be used, but not everyone wants to use it.
struct ReleaseCom {
template <class T>
void operator() (T* p) const
{
p->Release();
}
};
IComInterface* p = // co created or returned as a result
std::share_ptr<IComInterface> sp(p, ReleaseCom());
一种更不常见的情况-但仍然有效-是在dll,OS或库中自定义分配对象(句柄甚至原始内存)并具有必须调用的自身关联的清理函数(可能会或可能不会)依次调用 delete
.如果涉及内存分配,则 std :: allocate_shared
在不暴露原始指针的情况下,提供了对要使用的分配器的增强控制.
A more uncommon situation - but still valid - is when an object (handle or even raw memory) is custom allocated in a dll, OS or library and has it's own associated cleanup function that must be called (which may or may not call delete
in turn). If memory allocation is involved std::allocate_shared
offers more enhanced control of the allocator that is to be used without exposing a raw pointer.
我个人的感觉是,给定 std :: make_shared
和 std :: allocate_shared
,从原始指针构造 shared_ptr
的要求是越来越少.即使是以上情况,也可以包装到实用程序分配和管理功能中,从而从主要的业务逻辑代码中删除.
My personal feeling is that given std::make_shared
and std::allocate_shared
, the requirement to construct a shared_ptr
from raw pointers is becoming less and less. Even the cases above, can be wrapped into utility allocation and management functions, removing from the main business logic code.
这篇关于我什么时候想从原始指针构造一个共享指针的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!