shared_ptr临时对象是否有引用计数?赋值时会增加引用计数吗?
先看你的代码:
auto p = std::shared_ptr<int>(new int(42)); std::cout << p.use_count() << std::endl;
输出为1,这和你对《C++ Primer》内容的理解看似矛盾,其实是混淆了具名shared_ptr对象的拷贝和临时shared_ptr对象的移动两种场景,下面具体解释:
核心结论
- shared_ptr临时对象确实拥有引用计数:创建
std::shared_ptr<int>(new int(42))这个临时对象时,它会为指向的int对象初始化引用计数为1——此时只有这个临时指针指向内存。 - 临时对象作为右操作数时,不会触发引用计数递增:这里的
=不是普通赋值,而是触发了移动构造(C++11及以后标准),而非拷贝构造。
具体分析
场景1:具名对象的拷贝(符合Primer描述的情况)
如果代码是这样的:
std::shared_ptr<int> q(new int(42)); auto p = q; // 拷贝构造具名对象 std::cout << p.use_count() << std::endl; // 输出2
这时候才符合《C++ Primer》里说的“shared_ptr作为赋值右操作数时计数器递增”——q是具名对象,拷贝它会让两个shared_ptr共享同一块内存,引用计数从1递增到2,p和q的use_count都是2。
场景2:临时对象的移动(你的代码场景)
回到你的代码,std::shared_ptr<int>(new int(42))是一个临时对象,生命周期仅在这条语句中。C++标准为优化临时对象的使用,会触发移动构造函数:
- 移动构造会直接把临时对象内部的引用计数指针“转移”给p,而非复制一份并递增计数。
- 临时对象被移动后会变成空状态(不再指向那块内存),随后被销毁,不会影响引用计数。
- 最终只有p指向内存,所以use_count是1。
即使在没有移动语义的C++03环境下,过程会变成:临时对象被拷贝构造给p(计数变为2),然后临时对象销毁(计数减回1),最终结果还是1——只是中间多了一次计数的增减操作,但最终效果一致。
总结
- 临时shared_ptr有自己的引用计数,初始为1。
- 只有当右操作数是具名的shared_ptr对象时,拷贝操作才会递增引用计数。
- 临时对象作为右值时,会触发移动构造(或C++03下的拷贝+销毁),最终目标对象的use_count保持为1。
内容的提问来源于stack exchange,提问作者Chase Liu
相关产品推荐
相关产品推荐

