Dea*_*ean 3 c++ rvalue rvalue-reference
允许使用以下非常简单的代码:
class s
{
public:
};
const s& tt = std::move(s()); // Also valid without 'const'
Run Code Online (Sandbox Code Playgroud)
但是现在我想知道为什么允许它。
首先我们使用 std::move一个右值(临时值)并将其标记为右值引用,但是为什么左值引用可以绑定到右值引用?
是否因为右值引用也是右值?
导致左值引用绑定到右值引用的基本原理(或标准引号)是什么?我可以做到的。
编辑:msvc2015允许非常量左值引用绑定到右值引用,问题仍然是常量左值引用绑定到右值引用。抱歉,我应该指定我使用的编译器。
Rvalue引用作为标准转换之一(C ++标准的第4章)隐式转换为rvalues(更具体地说,转换为xvalues):
任何隐式转换的效果都与执行相应的声明和初始化,然后将临时变量用作转换的结果相同。如果T是左值引用类型或对函数类型(8.3.2)的右值引用,则结果为左值;如果T是对对象类型的右值引用,则结果为xvalue;否则为prvalue
可以将Rvalues(包括xvalues)绑定到constlvalue引用,以便可以将临时变量传递给具有此类参数的函数:
void foo(const bar &a);
// ...
foo(bar());
Run Code Online (Sandbox Code Playgroud)
(一个临时变量是一个右值;在这种情况下,结果bar()是一个右值)。我们没有理由不来允许这样做,因为临时始终只要生命视为含有表达-在这种情况下,函数调用-所以它不会产生一个参考晃来晃去里面foo。
这意味着始终可以将函数的签名调整fun(bar)为fun(const bar &)-并相应地更改实现!-因为临时参数仍将被接受,并且从调用者的角度来看语义应相同;const表示该对象将不会被修改,如果它是通过副本传递的,情况也是如此。
const不允许非参考;一个实际的原因是因为它们暗示应该以某种有意义的方式修改该值,并且如果该值是临时的,则将丢失该值。但是,如果确实要这样做,可以将一个右值转换为一个左值,但有一些注意事项,如对另一个问题的此答案所述。
const除了不知道通过引用传递临时参数之外,允许右值绑定到左值引用对于在不知道确切参数类型但又想允许移动语义的情况下也很有用。假设我正在调用一个可以定义为foo2(const bar &)或foo2(bar)并且在前一种情况下可能会或可能不会具有重载的函数foo2(bar &&),并且我想允许在可能的foo2(bar &&)情况下使用move语义(假设重载将在其函数中使用move语义)实施);我可以放心地std::move创建一个右值,因为在任何情况下它都适用。这个示例可能看起来有些虚构,但这是编写模板时可能会碰到的很多事情。在代码中:
bar bb = bar();
foo2(std::move(bb));
// above is legal if foo2 is declared as either:
// foo2(bar)
// foo2(const bar &)
// and in latter case calls overload foo2(bar &&) if it is defined.
Run Code Online (Sandbox Code Playgroud)
对于涉及临时的其他从右到左的引用分配,临时的生存期将扩展到引用的生存期,因此即使在参数传递以外的情况下也不会创建悬空引用:
const bar &b = bar(); // temporary lifetime is extended
Run Code Online (Sandbox Code Playgroud)
在上面,bar对象将不会被破坏,直到引用b超出范围。