从shared_ptr获取原始ptr并再次共享它

时间:2017-11-19 17:28:10

标签: c++ smart-pointers

为什么下面的代码不起作用?

class A {};

void f(A* a) {
    shared_ptr<A> c(a);
}

int main() {
    auto a = make_shared<A>();
    auto b = a.get();
    f(b);
    return 0;
}

f范围的最后,我的程序崩溃了。可能是什么导致了这个?是否有某些东西试图被删除而且不存在?

2 个答案:

答案 0 :(得分:5)

您有两个不相关的共享指针,它们都在尝试管理同一个资源。这导致了不确定的行为。特别是,当他们超出范围时,他们都会尝试删除资源。

一般情况下,不要这样做:)

答案 1 :(得分:2)

class A {};

void f(A* a) {
    shared_ptr<A> c(a);
}

int main() {
    auto a = make_shared<A>();
    auto b = a.get();
    f(b);
    return 0;
}

这里发生的事情是,您的初始make_shared()正在创建拥有shared_ptr的{​​{1}}。当您调用A时,您正在创建第二个不相关的共享指针,认为它拥有相同的数据。当函数调用f(b)结束时,本地共享ptr变量被销毁;这将检查引用计数是否为零(它将是),因此删除该对象。然后,当main函数结束时,局部变量f()的析构函数运行,检查引用计数是否为零(同样,它将是),因此尝试再次删除相同的数据。这种双重删除是造成崩溃的原因。

有两种解决方案:最简单的方法是不处理原始指针,并将a直接传递给shared_ptr。然后引用计数将正常工作,数据只会被销毁一次。

另一种方法是让您的班级f()公开继承自A。然后,您可以使用std::enable_shared_from_this方法从原始指针“恢复”共享指针(具有正确的引用计数),即

shared_from_this()

您可以阅读class A : public std::enable_shared_from_this<A> {}; void f(A* a) { shared_ptr<A> c = a->shared_from_this(); } here