C++11中的rvalue references(一):左值和右值(lvalue and rvalue)
来源:互联网 发布:网络兼职遭遇刷单陷阱 编辑:程序博客网 时间:2024/06/05 18:14
*
“If you’re an experienced C++ programmer and are anything like me, you initially approached C++11 thinking, “Yes, yes, I get it. It’s C++, only more so.” But as you learned more, you were surprised by the scope of the changes. auto declarations, range-based for loops, lambda expressions, and rvalue references change the face of C++, to say nothing of the new concurrency features. And then there are the idiomatic changes. 0 and typedefs are out, nullptr and alias
declarations are in. Enums should now be scoped. Smart pointers are now preferable to built-in ones. Moving objects is normally better than copying them.
- Effective Modern C++ by Scott Meyers*
*
这是大牛在Effective Modern C++中的一段对新C++特性的总结。其中rvalue references是一个比较核心的改进,对某些情况下对C++代码的效率很有帮助。最近在看相关的文档,笔者想写篇关于rvalue references的介绍性文章;准备分两部分:第一部分介绍下什么是rvalue和rvalue references,第二部分介绍它的应用。
lvalue 和 rvalue
lvalue和rvalue的概念最初来自C语言,后来C++对它们有所扩展。最初,在C里lvalue和rvalue貌似分别指一个赋值表达式的左边和右边值。(“L” stands for “left” and “R” stands for “right“)C++引入后,这个名字里左边啊,右边啊,就变得不那么清晰了;也就是C++里它们不再局限于赋值表达式的左边和右边了。
首先,有一点是肯定的,C++里一个表达式要么是lvalue的,要么是rvalue。这里有一点要强调,lvalue和rvalue的是表达式的属性,不是object的属性。(C++03 3.10/1 says: “Every expression is either an lvalue or an rvalue.”)
lvalue一般是有可以寻址的存储位置,它在表达式后还会存在(persist beyond a single expression)。rvalue一般是临时性的,在表达式后就会消失;所以rvalue是无法得到地址的,原因是如果可以得到临时东西的地址,那后续访问这个地址将是灾难性的。
还有一个判断lvalue和rvalue的小窍门是试着对表达式取地址(&);能合法取地址的是lvalue,不能取的或者得到荒谬结果的是rvalue。比如,&x,&x[0]都是合理的,所以x和x[0]都是lvalue;而&7,&(x+1),&(x+y)都是非法的,所以7,(x+1),(x+y)都是rvalue。
lvalue 和 rvalue的例子
下面举一些常见lvalue 和 rvalue的表达式。
以下是常见的lvalue:
int var = 0;var = 1 + 2; // ok, var is an lvalue hereint* p1 = &var; // ok, var is an lvalueobj , *ptr , ptr[index], ++x; // lvalue// function returned is rvalue, except it returns a referenceint x;int& getRef () { return x;}getRef() = 4; // lvalue, as getRef() returns a reference
常见的rvalue:
1 + 2;var + 1 = 2 + 3; // error, var + 1 is an rvalueint* p2 = &(var + 1); // error, var + 1 is an rvaluex++;// function returned is rvalue, except it returns a referenceint x;int getVal (){ return x;}getVal(); // rvalueUserType().member_function(); // ok, calling a member function of the class rvalue
上面有两点要注意的。第一是++x和x++。这两哥们很像,平时几乎没区别(除了一个是先加再取x的值,一个是先取x的值后加)。但其实这俩是完全不同的表达式:前者是lvalue后者是rvalue!++x和x++都是增加x值,但是++x返回的是原来的x,++后x依然存在;而x++返回的只是一个x的临时copy!
第二个要注意的是函数。只有返回引用时,函数才是lvalue;其他情况都是rvalue。
运算符重载中的 lvalue 和 rvalue问题
上面的例子中没有涉及到运算符重载;其实运算符重载和函数是一样的规则——只有返回引用时,运算符重载才是lvalue;其他情况都是rvalue。
reference operator[] (size_type n);vector<int> v(10, 1729); v[0]; // is an lvalue because operator[]() return reference int& .string operator+ (const string& lhs, const string& rhs);string s(“foo”);string t(“bar”);s + t; // is an rvalue because operator+() returns string (and &(s + t) is invalid).string& operator= (const string& str);s=t=p; // makes sense; as operator= is lvalue
lvalue 和 rvalue const属性
lvalue 和 rvalue 都可以是const或non-const的。比如:
string one(“cute”);const string two(“fluffy”);string three() { return “kittens”; }const string four() { return “are an essential part of a healthy diet”; }one; // modifiable lvaluetwo; // const lvaluethree(); // modifiable rvaluefour(); // const rvalueconst string&=three();
这里最关键的是引用(Type &)的变化。引用bind到 lvaue上,可以用来观察和修改变量值;所以非const引用不能作用于const lvaue和rvalue。作用于rvalue意味着可以修改临时变量值,这是绝对禁止的。
const引用(const Type &)可以bind到任何value上,lvalues, const lvalues, rvalues, and const rvalues (and can be used to observe them).
Refences
https://accu.org/index.php/journals/227
https://blogs.msdn.microsoft.com/vcblog/2009/02/03/rvalue-references-c0x-features-in-vc10-part-2/
- C++11中的rvalue references(一):左值和右值(lvalue and rvalue)
- 左值(lvalue)和右值(rvalue)
- 左值和右值(lvalue and rvalue)
- 关于左值与右值(lvalue & rvalue)
- [C/C++不常见语法特性]_[初级]_[左值-右值-lvalue-rvalue]
- C++ - 左值(lvalue)引用和右值(rvalue)引用 的 区别
- c语言中的lvalue和rvalue
- 【翻译】VC10中的C++0x新特性:右值引用(rvalue references) (1)
- 【翻译】VC10中的C++0x新特性:右值引用(rvalue references) (2)
- 【翻译】VC10中的C++0x新特性:右值引用(rvalue references) (3)
- lvalue and rvalue distanct
- rvalue and lvalue
- lvalue and rvalue
- 理解lvalue和rvalue
- C++11新特性: 右值引用 和 右值语义(rvalue sematics)
- C++11标准之右值引用(rvalue reference)
- lvalue和rvalue、传值和传引用、木桶
- lvalue和rvalue、传值和传引用、木桶
- java安全之AccessController
- 分布式搜索Elasticsearch——MultiSearch
- Spectrum的新一代16位数字化仪
- 畅通工程续 HDU
- 用动态sql实现报表数据的检测监控
- C++11中的rvalue references(一):左值和右值(lvalue and rvalue)
- 《算法艺术与信息学竞赛》之 枚举 例一 Balloons in a Box
- 2017.11.21大作业
- Axios说明文档
- 自动挡车驾车注意事项
- deep learning 专项课程二 dropout在代码中的使用
- 为什么好多公司的开发语言从C#变成了JAVA
- CAsyncSocket与CSocket的区别-同步和异步socket
- TextView 加中划线,下划线,抗锯齿,取消设置的线