从 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()
正在创建一个拥有 A
的 shared_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。
为什么下面的代码不起作用?
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()
正在创建一个拥有 A
的 shared_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。