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

Getting raw ptr from a shared_ptr and make it shared again

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

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 的范围末尾,我的程序崩溃了。是什么原因造成的?是否有试图删除但不存在的内容?

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

一般来说,不要这样做:)

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() 正在创建一个拥有 Ashared_ptr。当您调用 f(b) 时,您正在创建第二个不相关的共享指针, 认为它拥有相同的数据。当函数调用f()结束时,局部shared ptr变量被销毁;这将检查引用计数是否为零(它将为零),然后删除该对象。然后,当 main 函数结束时,局部变量 a 的析构函数运行,检查引用计数是否为零(再次,它将是),并尝试再次删除相同的数据。两次删除是导致崩溃的原因。

有几个解决方案:最简单的就是不处理原始指针,直接将 shared_ptr 传递给 f()。那么引用计数就会正常工作,数据只会被销毁一次。

另一种方法是让您的 class A 公开继承自 std::enable_shared_from_this。然后,您可以使用 shared_from_this() 方法从原始指针 "recover" 共享指针(具有正确的引用计数),即

class A : public std::enable_shared_from_this<A> {};

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

您可以阅读 enable_shared_from_this here