【发布时间】:2017-01-30 03:33:36
【问题描述】:
共享指针非常聪明。他们会记住最初构造时使用的类型,以便正确删除它们。以此为例:
struct A { virtual void test() = 0; };
struct B : A { void test() override {} };
void someFunc() {
std::shared_ptr<A> ptr1;
ptr1 = std::make_shared<B>();
// Here at the end of the scope, B is deleted correctly
}
但是,void 指针似乎存在一个问题:要使 void 指针的向下转换有效,必须将其向下转换为最初向上转换的类型。
例如:
void* myB = new B;
// Okay, well defined
doStuff(static_cast<B*>(myB));
// uh oh, not good!
// For the same instance of a child object, a pointer to the base and
// a pointer to the child can be differrent.
doStuff(static_cast<A*>(myB));
使用std::shared_ptr,当您使用std::make_shared 时,删除器必须类似于此函数:[](B* ptr){ delete ptr; }。由于指针(在第一个示例中)在指向 A 的指针中持有 B 实例并正确删除它,因此它必须以某种方式向下转换它。
我的问题是:下面的代码 sn-p 调用未定义的行为吗?
void someFunc() {
{
std::shared_ptr<void> ptr = std::make_shared<B>();
// Deleting the pointer seems okay to me,
// the shared_ptr knows that a B was originally allocated with a B and
// will send the void pointer to the deleter that's delete a B.
}
std::shared_ptr<void> vptr;
{
std::shared_ptr<A> ptr = std::make_shared<B>();
// ptr is pointing to the base, which can be
// different address than the pointer to the child.
// assigning the pointer to the base to the void pointer.
// according to my current knowledge of void pointers,
// any future use of the pointer must cast it to a A* or end up in UB.
vptr = ptr;
}
// is the pointer deleted correctly or it tries to
// cast the void pointer to a B pointer without downcasting to a A* first?
// Or is it well defined and std::shared_ptr uses some dark magic unknown to me?
}
【问题讨论】:
标签: c++ pointers shared-ptr void-pointers