如何在函数内部销毁std::shared_ptr?解决引用计数递增问题
嘿,这个问题刚好戳中了std::shared_ptr最核心的引用计数逻辑,咱们先拆解清楚为啥会出现这种差异,再聊聊怎么实现你想要的效果(先提前说:这真的是非常规操作,风险不小哦)。
为啥Delete函数里设nullptr没用?
当你把std::shared_ptr以值传递的方式传给Delete函数时,函数内部会创建一个原shared_ptr的拷贝——这时候引用计数会自动+1。你在函数里把这个拷贝设为nullptr,只会让这个拷贝的引用计数归0,而main里的那个原shared_ptr的引用计数还是1,所以对象根本不会被销毁。
简单说:你操作的是个“副本”,跟原对象没关系~
两种绕过引用计数递增的方法
方法1:传递shared_ptr的引用
把Delete函数的参数改成引用传递,这样函数里操作的就是main里的那个原shared_ptr,而不是拷贝。当你把它设为nullptr时,直接减少原引用计数,一旦计数归0,对象就会被销毁。
示例代码:
#include <memory> #include <iostream> class MyObj { public: ~MyObj() { std::cout << "对象已销毁!" << std::endl; } void Print() { std::cout << "Print调用成功" << std::endl; } }; // 这里用引用& void Delete(std::shared_ptr<MyObj>& sptr) { sptr = nullptr; // 直接操作原shared_ptr,引用计数减1至0,触发销毁 } int main() { auto sptr = std::make_shared<MyObj>(); Delete(sptr); // 注意:这里再调用sptr->Print()会直接崩溃,因为对象已经没了 return 0; }
方法2:用std::move转移所有权
通过std::move把main里shared_ptr的所有权转移给Delete函数的参数,这样函数参数拿到的是原shared_ptr的“所有权”,而不是拷贝——引用计数不会额外递增。当函数结束时,参数拷贝会被销毁,引用计数减1,如果原计数是1的话,对象就会被销毁,同时main里的sptr会变成空。
示例代码:
#include <memory> #include <iostream> class MyObj { public: ~MyObj() { std::cout << "对象已销毁!" << std::endl; } void Print() { std::cout << "Print调用成功" << std::endl; } }; void Delete(std::shared_ptr<MyObj> sptr) { // 函数结束时sptr会被销毁,引用计数减1 } int main() { auto sptr = std::make_shared<MyObj>(); Delete(std::move(sptr)); // 转移所有权到函数参数 if (!sptr) { std::cout << "main里的sptr已经是空的了" << std::endl; } return 0; }
重要提醒
这两种方法都能达成你的需求,但一定要注意:shared_ptr的设计初衷是安全共享对象所有权,强行在函数内销毁对象,很容易导致其他持有该对象的shared_ptr变成悬空指针,引发不可预料的崩溃。只有在你100%确定没有其他地方引用这个对象时,才考虑这么做哦。
内容的提问来源于stack exchange,提问作者user441521
相关产品推荐
相关产品推荐

