问题源于对条件接口的需求。可能是因为我陷入了XY问题,但是(底线)我最终需要一个共享指针(基于运行时选择)管理与否(拥有或不拥有)资源。
以下是关于非拥有共享指针
的一些想法使用placement new,例如:
struct MyStruct {};
MyStruct ms1;
std::shared_ptr<MyStruct> sp(new(&ms1) MyStruct);
使用虚拟删除
std::shared_ptr<MyStruct> spn(new MyStruct, [](MyStruct*){});
我的类布局(将使用非拥有共享指针)如下所示:
template<typename T>
struct blah
{
shared_ptr<T> _m;
};
现在,_m
成员可能会或可能不会拥有基于运行时选择的资源。我之所以不使用weak_ptr
,是因为_m
实际上可能是拥有指针。
答案 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
。
我选择了无操作删除器。设计可能看起来很奇怪,但如果你需要这样的行为(并且记录得足够多),它就会起作用。我在我的一个项目中使用了类似的东西一段时间,但后来我摆脱了它的需要。