const std::shared_ptr引用向上转型的工作机制探究
我发现当const std::shared_ptr&向上转型时,会创建一个指向同一转型后对象的基类新共享指针,示例代码如下:
#include <iostream> #include <memory> class Animal { }; class Cat : public Animal { }; void display(const std::shared_ptr<Animal>& animal) { std::cout << animal.use_count() << std::endl; } int main() { auto cat = std::make_shared<Cat>(); std::cout << cat.use_count() << std::endl; display(cat); std::cout << cat.use_count() << std::endl; }
运行这段代码的输出为:
sujith@AKLJoincggDLEd:~/sujith$ g++ -std=c++17 main.cpp sujith@AKLJoincggDLEd:~/sujith$ ./a.out 1 2 1 sujith@AKLJoincggDLEd:~/sujith$
我的疑问是:
- 这个行为是通过哪个运算符/构造函数实现的?
- 其他引用类型的向上转型也能获得相同行为吗?
- 还是说这是
shared_ptr引用特有的处理方式?
解答
1. 实现机制
这个行为是通过std::shared_ptr的模板转换构造函数实现的。C++标准库为shared_ptr定义了如下模板构造函数:
template <class Y> shared_ptr(const shared_ptr<Y>& r) noexcept;
当子类类型Y可以隐式向上转型为基类类型T(即Y*能转换为T*)时,这个构造函数会被触发:它会创建一个新的shared_ptr<T>实例,与原shared_ptr<Y>共享同一个控制块,因此引用计数会临时增加。
在你的代码中,调用display(cat)时,编译器会先构造一个临时的shared_ptr<Animal>,再将这个临时对象的引用绑定到函数的const std::shared_ptr<Animal>&参数上。函数执行完毕后,临时的shared_ptr<Animal>被销毁,引用计数随之下降,这就是输出出现1→2→1的原因。
2. 其他引用类型的向上转型行为
普通对象引用的向上转型不会有这种引用计数变化的行为。比如Cat&转Animal&,本质只是同一个对象的不同类型视角引用,不会创建任何新对象,也不存在引用计数的概念。这种涉及引用计数的临时对象创建行为,是智能指针这类需要管理对象生命周期的类型特有的。
3. 是否为shared_ptr引用特有
是的,这是shared_ptr(包括其引用形式)特有的处理方式。核心原因在于shared_ptr本身是一个管理原始指针的包装对象,而非原始指针或普通引用。当你传递shared_ptr<Cat>给期望const shared_ptr<Animal>&的函数时,编译器必须先构造一个兼容的shared_ptr<Animal>临时对象,才能完成参数绑定——这个临时对象的创建和销毁直接影响了引用计数。
内容的提问来源于stack exchange,提问作者Sujith Gunawardhane

