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



假设我们有一个期望按值的共享指针。(在现实生活中,我通过rvalue参考将其提交给会员。(

void f(std::shared_ptr<Derived> ptr) { ... }

,但我们只有一个共享指针指向基类,因此我们使用static_pointer_cast

std::shared_ptr<Base> ptr = std::make_shared<Derived>();
f(std::static_pointer_cast<Derived>(ptr));

第一个分配(从临时构建PTR(是否会触发原子增量和参考计数的减少,还是共享指针移动?(请注意,它正在被大量铸造。(

static_pointer_cast中,参考计数有原子增量。如果我们不再需要ptr,我们希望将其移至f中。但是,由于static_pointer_cast没有rvalue参考的过载,因此该动作不会产生任何效果:

f(std::static_pointer_cast<Derived>(std::move(ptr)));

我们仍然具有原子增量,一旦ptr破坏了相应的原子减少。为什么没有这样的超载?

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

std::shared_ptr<Base> ptr = std::make_shared<Derived>();

不会执行任何无关紧要的避风式增量/减少。首先,让我观察到这实际上不是一个任务,而是ptr的构造。显然,它是由临时性构建的,显然是暂时的类型。将匹配的构造函数的签名是(http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr(:

template< class Y > 
shared_ptr( shared_ptr<Y>&& r );

在注释中说:

MOVE-CONDSTRUCT从R中构造共享_ptr。构造后, *其中包含了R,R为空的先前状态的副本,其存储的指针为NULL。如果y*不隐式转换为t*

,模板过载不会参与过载分辨率

在这种情况下,YDerivedBase是CC_11,因此很明显,我们从Y*转换为T*,因此构造函数是合法的。严格来说,允许参考计数首先上升到2,然后降至1。但是显然这打败了移动构造函数的全部目的,因此我非常怀疑这就是如何实施。

相关内容

最新更新