shared_ptr使用场景,陷阱,性能分析与使用建议

举报
无敌清风蓝 发表于 2023/11/22 20:05:48 2023/11/22
【摘要】 shared_ptr使用场景,陷阱,性能分析与使用建议shared_ptr<int> create0(int value){ return make_shared<int>(value); //创建一个指向值为 10 的 int 对象的共享指针}void myfunc(int value){ shared_ptr<int>ptmp = create0(10); return; //ptmp...

shared_ptr使用场景,陷阱,性能分析与使用建议

shared_ptr<int> create0(int value)
{
	return make_shared<int>(value); //创建一个指向值为 10 的 int 对象的共享指针
}
void myfunc(int value)
{
	shared_ptr<int>ptmp = create0(10);
	return; //ptmp离开了作用域会被释放
}


int main() {
	myfunc(12); //这是12没用,单纯为了调用函数
	return 0;
}

改造一下myfunc

shared_ptr<int> myfunc(int value)
{
	shared_ptr<int>ptmp = create0(10);
	return ptmp; //这个return会导致引用计数+1,所以ptmp所指向的内存不会被释放,这相当于返回了一个ptmp的复制,ptmp销毁计数-1,return ptmp让计数+1
}

在main中调用myfunc,如果不用变量来接这个函数的返回结果的话,那么myfunc返回的shared_ptr会被销毁,它指向的对象也会被销毁,例如如果只有这样

myfunc(12); //返回的shared_ptr会被销毁,它指向的对象也会被销毁

如果有变量来接,则myfunc返回的shared_ptr不会被销毁,它指向的对象也不会被销毁,例如

auto p11 = myfunc(12);//此时p11是一个强引用

上面是使用场景,下面说说使用陷阱

—1.慎用裸指针

void proc(shared_ptr<int> ptr)
{
    return;
}
在main
int * p = new int(100);
// proc(p)  这是错的,int * p 不能转为shared_ptr<int>
proc(shared_ptr<int>(p)); //参数是一个临时的shared_ptr,用一个裸指针显式构造
*p = 45; //不可预料的后果,因为p指向的内存已经被释放了

一定要记住,把一个普通的裸指针绑定在shared_ptr上,那内存管理的责任就交给这个shared_ptr,这时候就不应该再使用裸指针访问shared_ptr指向的内存了

怎么修改这个问题呢

再main中

shared_ptr<int> myp(new int(100));
proc(myp);
*myp = 45; //myp是shared_ptr<>类型,*代表解引用

另外要注意,裸指针虽然可以初始化shared_ptr,但是不要用裸指针初始化多个shared_ptr

int * pi = new int;
shared_ptr<int> p1(pi);
shared_ptr<int> p2(pi); //p1一个引用,p2一个引用,会导致p1,p2两个指针之间没有任何关系(每个强引用计数都是1),所以释放时pi指向的内存释放了2次,这是会出问题的

为了避免这个问题,即使用裸指针,直接传递new运算符而不是传递一个裸指针变量,修改如下

shared_ptr<int> p1(new int); 这种写法大大降低了用pi来创建p2的可能性

—3.慎用get返回的指针

前面讲过get,get返回的指针不能delete,否则会有异常

shared_ptr<int> myp(new int(100));
int * p = myp.get(); //返回myp中保存的指针
delete p; //不能这样,会报错

也不能把其他智能指针绑定到get返回的指针上

shared_ptr<int> myp(new int(100));
int * p = myp.get() //这个指针千万不能随便释放,否则myp就没有办法正常管理该指针了
{
    shared_ptr<int> myp2(p); //这行代码万万不可,因为myp和myp2的引用计数都是1,但是一旦跳出这个程序块,往下看,其实这句代码会再程序执行结束时产生异常
}
//离开上面myp2的有限范围,导致myp指向的内存也被释放了
*myp = 100; //该内存已经释放,赋值会导致不可预料的后果

如何修改呢,修改{}里面的内容

{
    shared_ptr<int> myp2(myp); //执行后,myp和myp2引用计数都是2,跳出程序块后,myp2失效,myp引用计数恢复为1,myp可以正常使用
}

所以结论就是永远不要用get得到的指针来初始化另外一个智能指针或者给另外一个智能指针赋值

—4.循环引用

class CA;
class CB;
class CA
{
public:
	shared_ptr<CB> m_pbs;
	~CA()
	{
		cout << "~A()执行了" << endl;
	}
};
class CB
{
public:
	shared_ptr<CA> m_pas;
	~CB()
	{
		cout << "~B()执行了" << endl;
	}
};


int main() 
{
	shared_ptr<CA> pca(new CA);
	shared_ptr<CB> pcb(new CB);
	pca->m_pbs = pcb;
	pcb->m_pas = pca;
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。