多亏了std::make_shared,我想知道,作为原始指针的std::shared_ptr的构造函数是否有任何值,除了与遗留/库代码进行接口时(例如在存储工厂的输出时)。
shared_ptr<T>::reset(T*)?关于代码检查:我知道与遗留/库代码的接口很常见,所以自动化的代码检查可能会有问题,但在大多数情况下,到目前为止,我还是宁愿使用unique_ptr,我也不是在谈论在-Wall上弹出的编译器警告,而是在代码评审期间使用静态代码分析的规则。
我的动机:
说“不要使用std::shared_ptr<T>(new T(...))__,总是喜欢std::make_shared<T>(...)__”比较容易(我认为这是正确的建议?)。但是,我想知道这是不是一般的设计味道,是否必须从原始指针创建shared_ptr,甚至--尤其是--如果对象不仅仅是通过new创建的,因为对象本来应该是作为“共享”或“唯一”对象创建的。
发布于 2015-07-24 08:23:01
想到的第一个用例是,删除器不是默认的delete。
例如,在windows环境中,COM对象必须在某些时候使用,这些对象的发布必须通过Release对对象本身进行。当然,ATL是可以使用的,但并不是每个人都想使用它。
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提供了对分配程序的更强控制,该分配程序将在不公开原始指针的情况下使用。
我个人的感觉是,给定std::make_shared和std::allocate_shared,使用原始指针构造shared_ptr的要求越来越少。即使是上述情况,也可以包装成实用程序分配和管理功能,从主要业务逻辑代码中删除。
发布于 2015-07-24 08:40:03
Scott列出了有效的现代C++中的几个例外
第一个问题已被提及。如果需要提供自定义删除器,则不能使用make_shared。
第二种情况是,如果您所处的系统存在内存问题,并且您正在分配一个非常大的对象,那么使用make_shared为对象和包含弱引用计数的控制块分配一个块。如果您有指向对象的任何weak_ptr,则无法释放内存。另一方面,如果您没有使用make_shared,那么一旦删除了最后一个shared_ptr,就可以释放这个非常大的对象的内存。
发布于 2015-07-24 08:29:59
·还有其他合法的用例吗?
是的:在资源没有映射到新/删除的情况下:
handle_type APIXCreateHandle(); // third party lib
void APIXDestroyHandle(handle_type h); // third party lib在这种情况下,您将希望直接使用构造函数。
·避免使用构造函数是否合理?
当功能与make_shared重叠时,是的。
·同样的准则(不管是什么)是否适用于shared_ptr::reset(T*)?
如果你真的想要的话,你可以用一个std::make_shared调用的结果来代替重置调用。我宁愿看到重置调用,而不是-它的意图将更加明确。
关于代码检查:我知道与遗留/库代码的接口非常常见。
考虑将第三方库包装到一个接口中,以确保返回的值是唯一的_ptr-包装的。这将为您提供集中化点和其他方便/安全优化的机会。
说..。相对容易。但我不知道这是不是一般的设计味
使用它不是设计气味;只有当std::make_/:make_unique同样工作时才使用它。
编辑:为了解决问题的要点:您可能无法为此添加静态分析规则,除非您还向其添加了约定/异常列表(即“除了自定义删除层和第三方lib适配层之外,make_shared和make_unique应该始终被使用”)。对于您的一些文件,可能会跳过这样的规则。
但是,当您确实直接使用构造函数时,最好将它们放在专用于此的函数中(类似于make_unique和make_shared所做的):
namespace api_x
{
std::shared_ptr<handle_type> make_handle(); // calls APIXCreateHandle internally
// also calls the constructor
// to std::shared_ptr
}https://stackoverflow.com/questions/31605357
复制相似问题