我可以拥有非拥有的共享指针吗?

Nik*_*iou 6 c++ stl smart-pointers c++11 c++14

介绍

问题产生于对条件接口的需求.可能是因为我陷入了XY问题,但是(底线)我最终需要一个共享指针(基于运行时选择)管理或不管理(拥有或不拥有)资源.

到目前为止工作

以下是对非拥有共享指针的一些想法

  1. 使用placement new,例如:

    struct MyStruct {}; 
    MyStruct ms1; 
    std::shared_ptr<MyStruct> sp(new(&ms1) MyStruct); 
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用虚拟删除器

    std::shared_ptr<MyStruct> spn(new MyStruct, [](MyStruct*){}); 
    
    Run Code Online (Sandbox Code Playgroud)

  • 有标准的提议方式吗?
  • 是否存在"不做"规则?
  • 至少有更好的方法吗?

笔记

我的类布局(将使用非拥有共享指针)如下所示:

template<typename T>
struct blah
{
    shared_ptr<T> _m;
};
Run Code Online (Sandbox Code Playgroud)

现在,该_m成员可能拥有或可能不拥有基于运行时选择的资源.我没有使用的原因weak_ptr是因为_m实际上可能是一个拥有指针.

T.C*_*.C. 11

placement new显然是UB,因为它会在你的代码片段中尝试删除堆栈上的东西.空删除器版本将起作用,但将分配引用计数块.

诀窍是使用疯狂(ok,aliasing)构造函数shared_ptr:

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, T *ptr );
Run Code Online (Sandbox Code Playgroud)

构建一个shared_ptr拥有什么r,但指向什么ptr指向,即:

std::shared_ptr<MyStruct> sp(std::shared_ptr<MyStruct>(), p);
Run Code Online (Sandbox Code Playgroud)

这是noexcept由标准保证的,不会分配任何东西.该标准甚至还有一个说明

[ 注意:此构造函数允许shared_ptr 使用非null存储指针创建空实例.- 结束说明 ]


Rei*_*ica 7

该展示位置new将在销毁时为您提供未定义的行为(可能是崩溃) - 它会立即调用delete未创建的内容new.

我会选择无操作删除器.设计可能看起来很奇怪,但如果你需要这样的行为(并且记录得足够多),它就会起作用.我在我的一个项目中使用了类似的东西一段时间,但后来我摆脱了它的需要.

  • 我想摆脱它的需要是一个大赌注. (2认同)
  • 绝对是无操作的删除者; 这就是为什么boost有boost :: null_deleter,它曾一度埋在序列化代码中,但现在已经处于核心状态.当你需要诉诸于此时几乎总是很不幸,但是如果你不能改变API,你就不能......(编辑)如果你所做的只是试图拥有一个可能不拥有的指针,shared_ptr <>是过度的; 滚动你自己的便利类,或者使用unique_ptr和一个保留在布尔值周围的删除器来告诉它是否需要释放.如果在拥有案例中需要共享所有权,则shared_ptr可以 (2认同)