我希望保留std::shared_ptr
的智能行为。那么有没有一种方法可以将一个共享的空指针转换为另一种类型而不会影响引用计数?我不能获取原始指针并从中创建一个新的共享指针。
我希望保留std::shared_ptr
的智能行为。那么有没有一种方法可以将一个共享的空指针转换为另一种类型而不会影响引用计数?我不能获取原始指针并从中创建一个新的共享指针。
您可以使用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
也从不是任何动态类型的基类,因此 delete
一个 void*
就会触发未定义的行为。
shared_ptr exampleVoid(new MyClass)
部分,我已经纠正了。随意取消点赞来惩罚我口误 :P - Billy ONeal
void
不是所有类型的基类。C++并不是那么纯粹的面向对象。 - MSalters