为什么const shared_ptr<const T>&和const shared_ptr<T>&显示不同的引用计数?

11

以下代码片段展示了不同方法中的引用计数。有人可以解释一下为什么这些值是不同的吗?

class Foo {
};

void f1( const std::shared_ptr<Foo>& ptr ) {
   std::cout << "f1(): counts: " << ptr.use_count() << std::endl;
}

void f2( const std::shared_ptr<const Foo>& ptr ) {
   std::cout << "f2(): counts: " << ptr.use_count() << std::endl;
}

int main() {
   std::shared_ptr<Foo> ptr( new Foo );
   std::cout << "main(): counts: " << ptr.use_count() << std::endl;

   f1( ptr );
   f2( ptr );

   std::cout << "main(): counts: " << ptr.use_count() << std::endl;

   return 0;
}

相应的输出:

main(): counts: 1
f1(): counts: 1
f2(): counts: 2
main(): counts: 1

2
很可能f2调用时需要构造一个隐式临时对象,作为从shared_ptr<Foo>到shared_ptr<const Foo>的转换的一部分,这就是当f2执行时第二个引用计数来自的地方。 - Jeremy Friesner
谢谢!有道理。 - Arup Raton Roy
5
并不相关,只是提供信息:你应该使用make_shared而不是new。具体原因可以参考这篇文章:https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ - Tas
1
根本原因是C++在类模板参数上没有协变。 - Johannes Schaub - litb
1个回答

13
请注意,std::shared_ptr<Foo>std::shared_ptr<const Foo> 是不同的类型(即具有不同模板类型参数的类模板实例化是不同的类型)。
当您将ptr(即一个std::shared_ptr<Foo>)传递给f2时,它不能直接绑定到对std::shared_ptr<const Foo>的引用;必须构造一个临时的std::shared_ptr<const Foo>,然后将其绑定到参数ptr。新构造的shared_ptr与原始shared_ptr共享所有权,因此在f2()中,use_count增加到2
临时对象将在f2( ptr );结束时被销毁;然后use_count减少为1

我将初始化更改为 std::shared_ptr<const Foo> ptr( new Foo ); 并调用了 f2( ptr )。现在我可以看到引用计数没有增加。 - Arup Raton Roy
@ArupRatonRoy 是的,对于这种情况,没有临时的会造成麻烦。 - songyuanyao

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接