![](/img/trans.png)
[英]Dispatching r-values and l-values differently and using sfinae to disable one option
[英]Confused with r-values and l-values
我最近在C ++ 11的白皮书上读过,如果我写的话,
void foo(X&)
这将被称为l值而不是r值
如果我写,
void foo(const X&)
这将被调用r值和l值。
有人能给我一个例子,这意味着什么?
此函数接受左值引用
void foo(X&)
并试图用右值调用它会产生错误。
此函数需要一个const
左值引用
void foo(const X&)
但有一个问题:
可以使用右值来初始化const左值引用,在这种情况下,由rvalue标识的对象的生命周期被延长,直到引用的范围结束。
因此,最后一个函数接受左值和右值参数
struct X {};
void foo(X&) {
}
void fooC(const X&) {
}
int main() {
X obj;
// foo(std::move(obj)); // Error - non-const
foo(obj); // Valid
fooC(obj); // Valid
fooC(std::move(obj)); // Valid
}
有关更多信息,请查看此处: 参考初始化或检查[dcl.init.ref] / p5
考虑以下代码:
int i = 58;
什么是58
? 这是一个字面常量 。
因此: foo (const int&)
58
是一个r值(在这种情况下也是一个文字常量),因为你不能直接引用它,并且,比方说,修改它,因为没有办法做到这一点。 您可以引用i
因为它有一个名称,一个标识符,但58
本身没有标识符。
通俗地说,如果某些东西存在但它没有声明的名称你可以访问它然后它是一个常量和一个r值,除非你用r-val引用int &&引用它,那么你可以改变它。
int f();
...
int x = f(); //the returned int is an r-value, but x is an l-value
当你声明foo函数时
void foo(X&)
然后这样的代码将无法编译:
foo(5);
但如果你声明它:
void foo(const X&)
然后你可以这样称呼它:
foo(5);
const literal 5是一个r值,因为它没有名字。
粗略地说,rvalues是临时对象(从函数返回),而lvalues也是你可以引用的对象。
例如:
X bar();
X x = bar();
在该代码中(忽略可能的编译器优化),创建一个临时X对象来保存返回的foo值并传递给x
的copy-constructor,这个临时对象是一个rvalue,只存在于这个语句中,不能被引用代码的其他部分。 x
然后是左值,您可以检索其地址并在以后引用它。
这两个功能
void foo(X &);
void foo(const X &);
分别期待左值,非常量和常量。 后者接受rvalues的原因是因为rvalues可以转换为对lvalues的const引用。 也就是说,你可以这样做:
const X &ref = bar();
这里由bar()返回的临时值在ref
超出范围之前不会被销毁,因此它的生命周期已延伸到语句之外。 但是你不能对非const引用做同样的事情,
X &ref = bar(); // Error!
这是不允许的,因为bar的返回值是临时值(rvalue)并且无法修改。
但请注意,这不是C ++ 11的功能,这已经存在。 新功能是指定右值引用的功能
void foo(X &&);
void foo(const X &&);
这引入了更加微妙的情况,例如参见C ++ 11中的Universal References - Scott Meyers 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.