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

时间:2014-10-06 12:45:33

标签: c++ c++11 stl smart-pointers c++14

简介

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

到目前为止工作

以下是关于非拥有共享指针

的一些想法
  1. 使用placement new,例如:

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

    std::shared_ptr<MyStruct> spn(new MyStruct, [](MyStruct*){}); 
    
  3. 问题

    • 是否有标准的提议方式?
    • 是否有&#34;不要这样做&#34;规则?
    • 至少有更好的方法吗?

    备注

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

    template<typename T>
    struct blah
    {
        shared_ptr<T> _m;
    };
    

    现在,_m成员可能会或可能不会拥有基于运行时选择的资源。我之所以不使用weak_ptr,是因为_m实际上可能是拥有指针。

2 个答案:

答案 0 :(得分:11)

展示位置显然是UB,因为它会在你的代码段中尝试删除堆栈上的内容。空删除器版本将起作用,但将分配引用计数块。

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

template< class Y > 
shared_ptr( const shared_ptr<Y>& r, T *ptr );

构造shared_ptr拥有r所拥有的内容,但指向ptr指向的内容,即:

std::shared_ptr<MyStruct> sp(std::shared_ptr<MyStruct>(), p);

标准保证noexcept,并且不会分配任何内容。该标准甚至还有一个说明

的说明
  

[注意:此构造函数允许创建空shared_ptr   具有非null存储指针的实例。 - 结束记录]

答案 1 :(得分:7)

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

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