lvalues and rvalues
来源:互联网 发布:淘宝中心网页版登录 编辑:程序博客网 时间:2024/05/15 12:48
参考链接:https://msdn.microsoft.com/en-us/library/f90831hc.aspx
C++的任何表达式都是lvalue或者rvalue。lvalue指的是 在表达式之外依然一致的object,可以认为拥有名字的object都是lvalue,所以所有的变量都是lvalue。rvalue指的是 临时的值,在表达式之外使用就无法保证一致。
// lvalues_and_rvalues.cpp int main() { int i, j, *p; // Correct usage: the variable i is an lvalue. i = 7; // Incorrect usage: The left operand must be an lvalue (C2106). 7 = i; // C2106 j * 4 = 7; // C2106, 如果重载乘号返回的是一个左值,这里也可以是正确的// Correct usage: the dereferenced pointer is an lvalue. *p = i; const int ci = 7; // Incorrect usage: the variable is a non-modifiable lvalue (C3892). ci = 9; // C3892 // Correct usage: the conditional operator returns an lvalue. ((i < 3) ? i : j) = 7; }
欲详细了解rvalue、lvalue、xvalue、glvalue、prvalue 见stackoverflow
lvalue reference:可以认为左值引用就是另一个object的别名。用法为
type-id & cast-expression
rvalue reference:用法为
type-id && cast-expression
。move semantics
右值引用是一个作用为了支持move semantics :允许无法引用的临时对象资源被传递。(move senmatics的实现可以参照这里。)一个例子是string的operator+。在VC++ 2010以前,operator+并不能用于直接将两个string相加。因为如果两个string都是lvalue,则很有可能在其他地方被引用了,因此不能更改它们。而rvalue不能在程序其它地方引用,operator+就不用害怕意外改变了其它地方的值,因此可以将两个string相加。同样还有vector溢出处理的问题可以帮助理解,详细看这里。
int main() { string s = string("h") + "e" + "ll" + "o"; cout << s << endl; }
perfect forwarding
这里的forward的意思是一个泛型函数(比如模板函数)参数是引用参数,并将这些参数传递(forward)给其它函数。比如泛函数参数类型为const T&,则被调用的函数不能修改参数值。(而lvalue是允许修改的 )如果类型是T&,则函数不能传入rvalue调用(因为rvalue不能在其他修改,而T&允许修改参数 )。
比如针对如下类,要写一个调用他们的泛函数。
struct W { W(int&, int&) {} }; struct X { X(const int&, int&) {} }; struct Y { Y(int&, const int&) {} }; struct Z { Z(const int&, const int&) {} };
这是一个版本,但他只能调用左值,也就是允许在其他地方修改的值,要想代码正确需要一一实现对应的重载函数。
template <typename T, typename A1, typename A2> T* factory(A1& a1, A2& a2) { return new T(a1, a2); } int a = 4, b = 5; W* pw = factory<W>(a, b); Z* pz = factory<Z>(2, 2); // ERROR, rvalue, factory can only take lvalue reference
而rvalue reference允许只用下面一个泛函数解决问题:
template <typename T, typename A1, typename A2> T* factory(A1&& a1, A2&& a2) { return new T(std::forward<A1>(a1), std::forward<A2>(a2)); } // std::forward的作用是将factory函数的参数传给模板类的构造函数int main() { int a = 4, b = 5; W* pw = factory<W>(a, b); X* px = factory<X>(2, b); Y* py = factory<Y>(a, 2); Z* pz = factory<Z>(2, 2); }
允许facotry同时进行lvalue和rvalue调用的原因是由于reference collapsing rule的存在,可以对推测参数类型。
Template argument deduction is an important element of implementing perfect forwarding.
collapsing rule :
Expanded type Collapsed type T& & T& T& && T& T&& & T&& T&& && T&&比如以下例子:
c++
template<typename T>
void foo(T&&);- 当foo传进参数A类型是lvalue, 则编译器将T推测为A&, 根据collapsing rule, A& &&就是A&。
foo传进参数A类型是rvalue, 则T被推测为A, 因此A&&就是A&&。
更详细的,可参考stackoverflow上的解释。
还是没非常理解,需要多看看相关知识。。@_@
- Lvalues and Rvalues(转载)
- Lvalues and Rvalues
- lvalues and rvalues
- Lvalues and Rvalues in C#
- Understanding lvalues and rvalues in C and C++
- 左值和右值 Lvalues and Rvalues
- lvalues(&)和rvalues(&&)
- C++复习Lvalues,Rvalues,References
- 简要分析Pointers, Lvalues和 Rvalues
- Lvalues & Rvalues——理解左值与右值
- C++ 11 rvalues, lvalues, xvalues, glvalues, prvalues 是什么
- C++ 左值(Lvalues)和右值(Rvalues)
- *a++的含义及C语言中的左值(Lvalues)和右值(Rvalues)
- Two articles on C++ lvalues
- Item24 Distinguish universal references from rvalues reference
- c/c++中的lvaues(左值)和rvalues(右值)
- " and '
- $* and $@
- Aptana studio 3中的ArcGIS API For JS 的智能提示问题
- python使用备忘(一)
- SDUT-图的深度遍历
- Android6.0中申请权限在fragment中无回调
- ln 的使用
- lvalues and rvalues
- bzoj 3626: [LNOI2014]LCA(离线差分+树链剖分)
- 【多校训练】hdu 6043 KazaQ's Socks
- 第九章:django开发中发送邮件
- maven依赖本地非repository中的jar包
- Java知识:JVM内存模型的简单认识
- 大型网站架构模式
- MAC 搭建自动化测试环境(基于Appium+python+ios/android+unnitest+HTMLTestRunner)(一)
- oracle v$database 视图