RVO优化下shared_ptr引用计数、开销及对象生命周期问题
先针对你的示例代码逐一拆解核心疑问:
1. 引用计数会不会增减?
会。你的getA()函数返回的是成员变量m_a的拷贝——哪怕编译器做返回值优化(RVO),也无法直接复用m_a本身,因为RVO仅适用于函数内部创建的临时对象,而m_a属于Container实例的成员,函数返回时必须生成新的shared_ptr实例(触发拷贝构造),这会让引用计数+1;当这个临时shared_ptr在cont.getA()->action()表达式结束后销毁时,引用计数再-1。
这个场景下的引用计数增减无法通过RVO避免。
2. 能不能像裸指针一样无开销访问?
不能。只要是按值返回shared_ptr,哪怕是临时对象,也必然涉及引用计数的原子操作(加、减),这是shared_ptr的固有机制,无法跳过。
3. 如何避免引用计数开销?
如果你仅需调用对象方法、不需要持有shared_ptr,有两种更高效的方案:
- 返回裸指针:将
getA()的返回类型改为A*,直接返回m_a.get()。只要Container对象cont存活,且m_a未被重置,裸指针就有效。 - 返回**
shared_ptr的引用**:将返回类型改为shared_ptr<A>&,这样返回的是m_a本身的引用,不会触发拷贝,也就没有引用计数操作。但要注意,不能让这个引用的生命周期超过cont的生命周期,否则会出现悬垂引用。
4. 生命周期问题
在你的示例代码里,所有访问方式的生命周期都是安全的:
- 按值返回临时
shared_ptr时,临时对象会在整个cont.getA()->action()表达式执行完毕后才销毁,action()调用期间A对象必然存活。 - 如果返回裸指针或
shared_ptr引用,只要cont对象还存活(比如示例中cont是栈上对象,在当前作用域结束前都有效),m_a持有的A对象就不会被释放,访问安全。
内容的提问来源于stack exchange,提问作者Mix Kira
相关产品推荐
相关产品推荐

