const std::shared_ptr 引用向上转换如何工作?

Suj*_*ane 2 c++ casting shared-ptr

根据我的理解,当 const 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;
}
Run Code Online (Sandbox Code Playgroud)

上述代码的输出如下。

sujith@AKLJoincggDLEd:~/sujith$ g++  -std=c++17 main.cpp
sujith@AKLJoincggDLEd:~/sujith$ ./a.out
1
2
1
sujith@AKLJoincggDLEd:~/sujith$
Run Code Online (Sandbox Code Playgroud)

我的问题是哪个运营商执行此操作?对于其他引用向上转换,我们是否也可以获得相同的行为?或者是专门针对shared_ptr引用进行处理的?

感谢您对此进行调查。

bit*_*ask 6

执行此操作的函数是std::shared_ptr的构造函数,特别是重载 9:

template< class Y >
shared_ptr( const shared_ptr<Y>& r ) noexcept;
Run Code Online (Sandbox Code Playgroud)

这些是语义:

构造一个shared_ptr,它共享r管理的对象的所有权。如果 r 不管理任何对象,则 *this 也不管理任何对象。如果 Y* 不能隐式转换为(C++17 之前)与(C++17 起)T* 兼容,则模板重载不会参与重载决策。

重要的是最后一句话。您的Cat*(Y*) 可转换为/与您的Animal*(T*) 兼容。因此,该构造函数参与重载决策并被选择,因为它是唯一可用的(其他重载不匹配)。


std::shared_ptr这是一个简化的示例,突出显示了在引用的重载中使用的一般概念如何工作:

struct A{};

struct B {
  B(A const& a) {}
};

void foo(B const&) {}

int main() {
  A a;
  foo(a);
}
Run Code Online (Sandbox Code Playgroud)

调用通过foo隐式创建一个B对象B::B(A const&)foo然后传递一个对该临时B对象的 const 引用。

事实上,在您的示例中,BA是源自同一类模板的类型并不重要。