有没有办法将shared_ptr投射<void>到shared_ptr<T>?

Is there a way to cast shared_ptr<void> to shared_ptr<T>?

本文关键字:gt lt ptr shared void 投射 有没有      更新时间:2023-10-16

我想保持std::shared_ptr的智能行为。那么,有没有一种方法可以将共享的void指针强制转换为另一种类型,同时又不会混淆引用计数?我无法获取原始指针并从中创建新的共享指针。

您可以使用rob-mayoff的答案中的指针强制转换;但是要小心。这里很容易无意中触发未定义的行为:

struct MyClass {};
void* rawPtr = new MyClass;
shared_ptr<void> exampleVoid(rawPtr); // Undefined behavior;
                                      // calls delete (void*)ptr;
shared_ptr<void> exampleVoidCons(new MyClass);
    // OK, calls shared_ptr<void>::shared_ptr<MyClass>(MyClass*) which
    // makes a deleter calling delete (MyClass*)ptr;
shared_ptr<MyClass> example(new MyClass); // OK, calls delete (MyClass*)ptr;
shared_ptr<void> castToVoid = static_pointer_cast<void>(example);
    // OK, shared_ptr's deleter is erased so this still calls delete (MyClass*)ptr;

通常,这种未定义的行为将导致类型的析构函数不被调用。例如,请参阅ideone上的输出,并注意放入void*的版本从未打印出它已被销毁。


参见C++11 5.3.5[expr.delete]/3:

在第一种选择(删除对象)中,如果要删除的对象的静态类型与其动态类型不同,则静态类型应为要删除对象的动态类型的基类,并且静态类型应具有虚拟析构函数或行为未定义。

由于实际对象永远不会具有动态类型void,并且void永远不会是动态类型的基类,因此deletevoid*会触发未定义的行为。

您可以使用std::static_pointer_caststd::dynamic_pointer_cast,具体取决于您想要的类型。