std :: move into static_pointer_cast:为什么static_pointer_cast没有rvalue引用重载?

has*_*rsn 6 c++ c++11

假设我们有一个函数,期望按值共享指针.(在现实生活中的例子中,我通过右值引用将其转发给成员.)

void f(std::shared_ptr<Derived> ptr) { ... }
Run Code Online (Sandbox Code Playgroud)

但是我们只有一个指向基类的共享指针,所以我们使用static_pointer_cast:

std::shared_ptr<Base> ptr = std::make_shared<Derived>();
f(std::static_pointer_cast<Derived>(ptr));
Run Code Online (Sandbox Code Playgroud)

第一个赋值(从临时构造ptr)是触发引用计数的原子递增和递减还是共享指针移动?(注意它正在升级.)

在内部static_pointer_cast有一个引用计数的原子增量.如果我们不再需要ptr,我们希望将其移入f.但由于没有超载static_pointer_cast参与右值参考,此举不会产生任何影响:

f(std::static_pointer_cast<Derived>(std::move(ptr)));
Run Code Online (Sandbox Code Playgroud)

一旦ptr被破坏,我们仍然有原子增量和相应的原子减量.为什么没有这样的超负荷?

Nir*_*man 3

我可以回答你问题的第一部分,但不能回答第二部分。虽然我不确定标准是否强制要求,但我很确定:

std::shared_ptr<Base> ptr = std::make_shared<Derived>();
Run Code Online (Sandbox Code Playgroud)

不会进行任何无关的引用计数器递增/递减。首先,让我观察一下,这实际上根本不是一个作业,而是ptr. 显然它是由临时建筑建造的,而且显然临时建筑属于不同类型。将匹配的构造函数的签名是(http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr):

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

注释中写道:

从 r 移动构造一个shared_ptr。构造完成后,*this 包含 r 先前状态的副本,r 为空,其存储的指针为 null。如果 Y* 不能隐式转换为 T*,则模板重载不会参与重载决策

在本例中,YisDerivedTis Base,很明显我们得到了从Y*to的隐式转换T*,因此构造函数是合法的。严格来说,允许引用计数首先上升到 2,然后再下降到 1 可能是符合要求的。但显然这违背了移动构造函数的全部目的,所以我非常怀疑这就是它的实现方式。