sky*_*ack 22 c++ casting shared-ptr unique-ptr c++11
我知道使用static_pointer_castwith unique_ptr会导致所包含数据的共享所有权.
换句话说,我想做的是:
unique_ptr<Base> foo = fooFactory();
// do something for a while
unique_ptr<Derived> bar = static_unique_pointer_cast<Derived>(foo);
Run Code Online (Sandbox Code Playgroud)
无论如何,这样做的结果是两个unique_ptr不应该同时存在,所以它只是被禁止.
是的,绝对有道理,这就是为什么不存在static_unique_pointer_cast确实存在的原因.
到目前为止,在我想存储指向这些基类的指针的情况下,但我还需要将它们转换为某些派生类(例如,想象一下涉及类型擦除的场景),我使用了shared_ptrs因为我的'如上所述.
无论如何,我猜测是否有替代方案可以shared_ptr解决这样的问题,或者在这种情况下它们是否真的是最佳解决方案.
Ane*_*dar 32
你的问题的解决方案是获取原始(非拥有)指针并将其unique_ptr<Base>强制转换- 然后让原始指针超出范围,让剩余的指针控制所拥有对象的生命周期.
像这样:
unique_ptr<Base> foo = fooFactory();
{
Base* tempBase = foo.get();
Derived* tempDerived = static_cast<Derived*>(tempBase);
} //tempBase and tempDerived go out of scope here, but foo remains -> no need to delete
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用release()函数将unique_ptr其包装到另一个unique_ptr中.
像这样
template<typename TO, typename FROM>
unique_ptr<TO> static_unique_pointer_cast (unique_ptr<FROM>&& old){
return unique_ptr<TO>{static_cast<TO*>(old.release())};
//conversion: unique_ptr<FROM>->FROM*->TO*->unique_ptr<TO>
}
unique_ptr<Base> foo = fooFactory();
unique_ptr<Derived> foo2 = static_unique_pointer_cast<Derived>(std::move(foo));
Run Code Online (Sandbox Code Playgroud)
请记住,这会使旧指针无效 foo
只是为了完整答案,这个解决方案实际上是由OP在评论中对原始指针的一个小修改.
与使用原始指针类似,可以转换原始指针,然后通过derefering从中创建引用.在这种情况下,重要的是要保证创建的引用的生命周期不超过unique_ptr的生命周期.
样品:
unique_ptr<Base> foo = fooFactory();
Derived& bar = *(static_cast<Derived*>(foo.get()));
//do not use bar after foo goes out of scope
Run Code Online (Sandbox Code Playgroud)
我知道将static_pointer_cast与unique_ptr一起使用会导致所包含数据的共享所有权.
只有你定义得很糟糕.显而易见的解决方案是转移所有权,以便源对象最终为空.
如果您不想转让所有权,那么只需使用原始指针即可.
或者,如果你想要两个所有者然后使用shared_ptr.
看起来你的问题只是部分关于实际的转换操作,部分只是指针缺乏明确的所有权政策.如果您需要多个所有者,无论他们是否使用相同类型,或者是否将其转换为其他类型,那么您不应该使用unique_ptr.
无论如何,使用两个不应该同时存在的unique_ptr会导致结果,因此它被禁止.
是的,绝对有道理,这就是为什么不存在像static_unique_pointer_cast那样的东西.
不,这不是它不存在的原因.它不存在,因为如果你需要它自己编写它是微不足道的(并且只要你给它独特所有权的理智语义).只需将指针弹出release(),然后将其放入另一个指针中unique_ptr.简单安全.
情况并非如此shared_ptr,"明显的"解决方案没有做正确的事情:
shared_ptr<Derived> p2(static_cast<Derived*>(p1.get());
Run Code Online (Sandbox Code Playgroud)
这将创建两个shared_ptr拥有相同指针的不同对象,但不共享所有权(即它们都会尝试删除它,导致未定义的行为).
当shared_ptr第一次标准化时,没有安全的方法来做到这一点,因此static_pointer_cast定义了相关的铸造功能.他们需要访问shared_ptr簿记信息的实施细节才能工作.
但是,在C++ 11期间,标准化过程shared_ptr通过添加"别名构造函数"得到了增强,它允许您简单安全地执行转换:
shared_ptr<Derived> p2(p1, static_cast<Derived*>(p1.get());
Run Code Online (Sandbox Code Playgroud)
如果这个特征一直是其中的一部分,shared_ptr那么它可能,甚至可能是static_pointer_cast永远不会被定义的.