C++:左值引用和右值引用的转换

apr*_*ori 9 c++ rvalue-reference c++14

我想知道标准的哪些部分在以下代码段中指定:

#include <memory>

class A { };

class B : public A { };

int main()
{
    std::unique_ptr<B> bptr = std::make_unique<B>(); // (a)
    std::unique_ptr<A> aptr = std::move(bptr);       // (b)
    std::unique_ptr<A> &aptr_r = bptr;               // (c)
    std::unique_ptr<A> &&aptr_rr = std::move(bptr);  // (d)
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

(d)编制而且(c)没有编制.请在答案中包含标准的相关部分或适当参考.仅供参考,Ubuntu clang版本3.6.2-1(标签/ RELEASE_362/final)(基于LLVM 3.6.2)给了我

error: non-const lvalue reference to type 'unique_ptr<A>' cannot
       bind to a value of unrelated type 'unique_ptr<B>'
       std::unique_ptr<A> &aptr_r = bptr;
                           ^        ~~~~
Run Code Online (Sandbox Code Playgroud)

gcc(Ubuntu 5.2.1-22ubuntu2)5.2.1 20151010给了我

error: invalid initialization of reference of type ‘std::unique_ptr<A>&’
       from expression of type ‘std::unique_ptr<B>’
       std::unique_ptr<A> &aptr_r = bptr;
                                    ^
Run Code Online (Sandbox Code Playgroud)

编辑:

为了使我的问题更清楚,让我补充一下

class C { };

std::unique_ptr<C> cptr = std::make_unique<C>(); // (e)
std::unique_ptr<A> &&aptr_rr2 = std::move(cptr); // (f)
Run Code Online (Sandbox Code Playgroud)

什么是保持(f)编译时(d)?明显AC无关,但如果是,当检测到std::unique_ptr使用的构造来构建临时两个(d)和(f)是

template<class U, class E>
unique_ptr(unique_ptr<U, E> &&u);
Run Code Online (Sandbox Code Playgroud)

Col*_*mbo 4

您的情况之间的主要区别在于,右值引用可以间接绑定(通过临时),而非左const值引用则不能。在 (c) 和 (d) 中,初始化器与 [dcl.init.ref]/(5.1)中确定的类型不相似或不可转换 ,因此 [dcl.init.ref]/(5.2) 必须适用 - 立即排除 (c):

否则,该引用应为非易失性const类型的左值引用(即,cv1应为 const),或者该引用应为右值引用。

另请注意,unique_ptr<A>unique_ptr<B>是不同的、不相关的类型,无论AB是如何相关的。

您也可以使用标量观察该规则:

int&& i = 0.f; // Ok
int& i = 0.f; // Not ok
Run Code Online (Sandbox Code Playgroud)