注意:如果不是CSDN网站显示本篇文章,请于底部点击“阅读原文”来阅读本篇文章!
作为一项案例分析下,C++函数中返回智能指针的裸指针问题。
要点
不要在函数中返回智能指针的裸指针出去!
原始代码
作用是获取一个插件的service。plugin->GetService()
返回的是一个std::shared_ptr
智能指针
Service *Test::GetService() const // 函数声明
Service *Test::GetService() const // 函数实现
{
auto plugin = PluginManager::Instance()->GetPlugin(m_type);
return plugin->GetService().get();
}
问题:如果使用智能指针的.get方法,获取一个裸指针返回,那么plugin->GetService()
这里会得到一个临时智能指针变量,它生成临时变量时,计数器加1,函数返回后,这个临时变量会被销毁,此处计数器会减1,那么智能指针所指的内存会被释放,但是这里的释放不一定内存就没了,也不会马上就会被其他程序占用,所有此时这个get返回的地址就是一个野指针了。
写一个完整的测试代码,如下:
#include <iostream>
#include <string>
using namespace std;
class Test
{
public:
Test() {
cout<<"struct test"<<endl;
}
~Test() {
cout<<"destruct test "<<m_a<<" addr: "<<this<<endl;
}
string m_a {"sldj"};
int m_b {2};
};
std::shared_ptr<int> GetInt(int num)
{
return std::make_shared<int>(num);
}
int* GetIntTmp() {
auto p = GetInt(10);
std::cout<<p.use_count()<<endl;
cout<<p<<" : "<<p.get()<<endl;
return p.get();
}
std::shared_ptr<Test> GetTest()
{
return std::make_shared<Test>();
}
Test* GetTestTmp() {
auto p = GetTest();
cout<<p<<" : "<<p.get()<<endl;
return p.get();
}
int main(int argc, char *argv[])
{
auto q = GetTestTmp();
cout<<q<<endl;
cout<<q->m_a<<endl;
return 0;
}
输出打印如下,确实test的析构被调用了。
![在这里插入图片描述](https://img-blog.csdnimg.cn/c8a6763387124c64956d1d901f6af3a6.png)
解决办法
1、 直接返回一个智能指针给外面用
std::shared_ptr<Service> Test::GetService() const
{
auto plugin = PluginManager::Instance()->GetPlugin(m_type);
return plugin->GetService().get();
}
2、或者使用std::move的方式移走,让指向的内存不被析构
微信公众号搜索:“上官宏竹”,关注并留言咨询,可接各类需求。