boost::shared_ptr:传值还是传引用?

关于shared_ptr

shared_ptr,顾名思义,是共享指针。boost库引入shared_ptr为了实现在C++中通过引用计数对堆对象进行内存管理的一种机制。更多关于shared_ptr的信息,可参考shared_ptr template.

一般可以通过以下方式使用shared_ptr:



boost::shared_ptr<classa> sp1(new classa());
boost::shared_ptr<classa> sp2 = sp1;


shared_ptr对象最初创建时的reference count为1,表示当前存在一个指向对象的引用;将sp1通过赋值操作符(=)赋值给sp2后,shared_ptr对象的reference count则会增1,表明又多了一个指向对象的引用。

当推出shared_ptr对象所在的作用域(函数体,代码块,或者是用作返回值或传值参数的临时对象)时,shared_ptr的析构函数就会被调用,此时reference count就会减1,当reference count减到0时才会delete所引用的内存对象。如此便实现了对内存对象的自动管理,程序员不在用去担心何时去delete一个对象,delete一个对象会不会导致一个dangling指针,这些shared_ptr都帮你搞定了。

然而,但凡C/C++中涉及到释放内存资源的一类问题,都要小心使用,否则尽管有shared_ptr,仍可能出现一些隐藏的bug,比如在使用shared_ptr作为参数传递时。


传值还是传引用?

C/C++的函数参数传递有两种方式:传值(pass-by-value)和传引用(pass-by-reference).

void pass_by_value(t t);
pass_by_value(t0);
void pass_by_reference(const t& t);
void pass_by_reference2(t& t);


传值方式会带来一次额外的对象拷贝构造函数调用开销,在pass_by_value中,编译器会调用T的拷贝构造函数从t0构造出一个新的临时的T对象用作pass_by_value的参数,这个对象在函数pass_by_value函数调用结束后会自动析构。

而传引用方式不存在这次额外的构造函数调用,可以简单的理解为传了一个地址作为pass_by_reference的参数。

当构造一个T对象开销很大时,显然,传引用方式具有明显的性能优势。

对于shared_ptr对象,究竟哪种方式更好呢?


// case 1: pass by value
void pass_shared_ptr(boost::shared_ptr<t> t);
// case 2: pass by reference
void pass_shared_ptr(const boost::shared_ptr<t>& t){
   ...
   t->dosomething();
}


两种情况的区别正如上述,第一种情况多了一次额外的shared_ptr对象拷贝构造函数的调用。 乍一看,还是传引用的好,但事实并非如此。

使用shared_ptr对象隐含一个假设,就是在shared_ptr对象的作用范围中,它一定指向一个存在并有效的内存对象,也就是说它的引用计数一定为1。在传引用的情况下,如果...代码中对shared_ptr对象有副作用时,比如传入的t是一个对象的成员变量而这个对象又正好被释放了,那么这个shared_ptr的引用计数可能被减为0从而导致所指对象的释放,然后悲剧就发生了,t->doSomething(), 企图在t上解引用去调用一个方法将会导致segment falut。但这毕竟是一个由于code不小心而引入的意外,如果你能确保...代码块中没有对t的副作用,传引用也不会存在大问题。然而,防范于未然应当是每个程序员的编程习惯。

再说说传值,额外多出的一次对象拷贝正是保证了在shared_ptr对象的作用域中它一定能指向一个有效的内存对象这一假设,而shared_ptr对象的拷贝算不算上是重量级的。这个优化实际上没有多大意义。

所以,传递shared_ptr参数还是用传值更好!



总结

如果出于性能优化的目的使用传引用方式,那么需要做的前期工作是对程序进行profile,找出瓶颈在什么地方,然后有的放矢地进行优化,如果由于传值导致性能问题,那么就要坚决地使用传引用,并且要额外注意对象的生命周期,避免因优化而带来的regression或潜在的bug。

总之,还是一句话,C++操作内存对象时要多一个心眼,哪怕是有一些高级的工具帮助我们简化这些工作。









  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值