C++98中规定了左值和右值的概念,但是一般程序员不需要理解的过于深入,因为对于C++98,左值和右值的划分一般用处不大,但是到了C++11,它的重要性开始显现出来。

C++98标准明确规定:

左值是可以取得内存地址的变量。

非左值即为右值。

从这里可以看出,可以执行&取地址的就是左值,其他的就是右值。

这里需要明确一点,能否被赋值不是区分C++左值和右值的区别。

我们给出四个表达式:

  1. string one("one");
  2. const string two("two");
  3. string three() { return "three"; }
  4. const string four() { return "four"; }

这里四个变量表达式,后面两个是临时变量,不可以取地址,所以属于右值,前面两个就是左值。

这里写出一个函数:

  1. void test(const string &s)
  2. {
  3. cout << "test(const string &s):" << s << endl;
  4. }

然后进行测试:

  1. test(one);
  2. test(two);
  3. test(three());
  4. test(four());

编译我们发现,这个test可以接受所有的变量。

我们使用另一个函数做测试:

  1. void test(string &s)
  2. {
  3. cout << "test(string &s):" << s << endl;
  4. }

然后测试发现,只有one可以通过调用。

然后我们同时提供两个test函数,然后我们编译运行发现:

  1. test(string &s):one
  2. test(const string &s):two
  3. test(const string &s):three
  4. test(const string &s):four

 

所以我们可以得出结论:

在C++中,const X&可以接受所有的变量

X &只可以接受普通变量

同时我们可以看出C++重载决议的一个特点:

当一个参数可以匹配多个函数时,总是匹配最精准的一个。

例如上面的one,它也可以接受const X&,但是当X&形式的参数存在时,立刻选择后者。显然后者是专门为其准备的,二者的语义最为符合。X&包含有一种修改语义,这与one是一致的。

 

引入const属性

 

上面的四个表达式,我们只讨论了左值和右值,我们再加上const进行讨论。

所以:

  1. string one("one"); 属于非const左值
  2. const string two("two"); const左值
  3. string three() { return "three"; } const右值
  4. const string four() { return "four"; } const右值
  1. 左值右值的属性与const是正交的。
  1. 现在引入一个问题,如果有时候需要区分四种变量,那么该使用什么方法?
  1. 前面的讨论,我们知道X&可以用来区分one,但是剩下的三个都可以被const X&吞掉,显然我们需要为一些变量提供一些定制版本的参数,来让不同的变量优先选择不同的参数。
  1. C++11提供了右值引用来专门区分右值,我们同时提供四个函数:
  1. void test(const string &s)
  2. {
  3. cout << "test(const string &s):" << s << endl;
  4. }
  5.  
  6. void test(string &s)
  7. {
  8. cout << "test(string &s):" << s << endl;
  9. }
  10.  
  11. void test(string &&s)
  12. {
  13. cout << "test(string &&s):" << s << endl;
  14. }
  15.  
  16. void test(const string &&s)
  17. {
  18. cout << "test(const string &&s):" << s << endl;
  19. }

我们使用C++11进行编译,发现:

  1. test(string &s):one
  2. test(const string &s):two
  3. test(string &&s):three
  4. test(const string &&s):four

我们得出最佳匹配:

 

X & 匹配 非const左值

const X& 匹配 const左值

X && 匹配 非const右值

const X && 匹配 const右值

然后,我们可以采用逐个函数进行测试,发现:

X& 仅仅匹配 非const左值,这与之前的结论一致

const X& 可以匹配所有的表达式

X && 只可以匹配 非const右值

const X &&可以匹配const和非const 右值

OK,我们的问题解决,当我们需要区分右值的时候,就可以使用右值引用。

事实上,我们一般不需要const X &&,所以我们使用下列三种参数:

 

void test(string &s); 修改语义

void test(string &&s); 移动语义,后文介绍

void test(const string &s); 常量语义

这三种语义已经足够,在C++98中我们只使用修改和常量语义,在C++11中,正是为了实现移动语义,我们才需要区分右值,才需要引入右值引用

 

下文讲C++11右值引用实现移动语义。

C++11之右值引用(一):从左值右值到右值引用的更多相关文章

  1. 你好,C++(11)如何用string数据类型表示一串文字?根据初始值自动推断数据类型的auto关键字(C++ 11)

    3.5.2  字符串类型 使用char类型的变量我们可以表示单个字符,那么,我们又该如何表示拥有多个字符的字符串呢? 我们注意到,一个字符串是由多个字符串连起来形成的.很自然地,一种最简单直接的方法就 ...

  2. 如何引用传递String Boolean 等,并改变他们的值

    如何引用传递String Boolean 等,并改变他们的值 采用list, 在存入位置改变list的值 如 list.add(true); list.remove(0); list.add(fals ...

  3. 值传递:pass by value(按值传递) 和 pass by reference(引用传递)-[all]-[编程原理]

    所有的编程语言,都会讨论值传递问题. 通过一个js示例直观认识 //理解按值传递(pass by value)和按引用传递(pass by reference) //pass by value var ...

  4. 第11.17节 Python 正则表达式扩展功能:命名组功能及组的反向引用

    一. 引言 在<第11.16节 Python正则元字符"()"(小括号)与组(group)匹配模式>介绍了组匹配模式,在一个正则表达式内可以定义多个组,每个组都有一个顺 ...

  5. 【C/C++】引用&的含义/语法/作为函数参数/函数返回值/本质/常量引用

    含义 引用不产生副本,只是给原变量起了别名. 对引用变量的操作就是对原变量的操作. 基本语法 数据类型 &别名 = 原名 e.g. int a = 10; int &b = a; // ...

  6. 弱引用?强引用?未持有?额滴神啊-- Swift 引用计数指导

    ARC ARC 苹果版本的自动内存管理的编译时间特性.它代表了自动引用计数(Automatic Reference Counting).也就是对于一个对象来说,只有在引用计数为0的情况下内存才会被释放 ...

  7. 创建一个接口Shape,其中有抽象方法area,类Circle 、Rectangle实现area方法计算其面积并返回。又有Star实现Shape的area方法,其返回值是0,Star类另有一返回值boolean型方法isStar;在main方法里创建一个Vector,根据随机数的不同向其中加入Shape的不同子类对象(如是1,生成Circle对象;如是2,生成Rectangle对象;如是3,生成S

    题目补充: 创建一个接口Shape,其中有抽象方法area,类Circle .Rectangle实现area方法计算其面积并返回. 又有Star实现Shape的area方法,其返回值是0,Star类另 ...

  8. mysql内连接(inner join 找两个表的交集)、左连接(left join 交集并且左表所有)、右连接(right join 交集并且右表所有)、全连接(mysql不支持)

    用两个表(a_table.b_table),关联字段a_table.a_id和b_table.b_id来演示一下MySQL的内连接.外连接( 左(外)连接.右(外)连接.全(外)连接). MySQL版 ...

  9. 数据库中的左连接(left join)和右连接(right join)区别

    Left Join / Right Join /inner join相关 关于左连接和右连接总结性的一句话: 左连接where只影向右表,右连接where只影响左表. Left Join select ...

  10. “DBUtility.DbHelperSQL”的类型初始值设定项引发异常 “DBUtility.DbHelperSQL”的类型初始值设定项引发异常

    今天遇到了一个这样的问题“DBUtility.DbHelperSQL”的类型初始值设定项引发异常“DBUtility.DbHelperSQL”的类型初始值设定项引发异常 也许有和我遇到这问题的人也在这 ...

随机推荐

  1. linux和shell关系

    坚持知识分享,该文章由Alopex编著, 转载请注明源地址: http://www.cnblogs.com/alopex/   索引: 什么是shell shell的分类 shell脚本的执行方式   ...

  2. 管理页面的类 PageHelper

    using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Da ...

  3. Spring中报"Could not resolve placeholder"的解决方案(引入多个properties文件)

    除去properites文件路径错误.拼写错误外,出现"Could not resolve placeholder"很有可能是使用了多个PropertyPlaceholderCon ...

  4. eclipse 导出burpsuite插件包含第三方lib包

    第一步:右键项目点击export: 2.选择Runable JAR file: 点击Finish后会爆出一个错误(Jar export finished with problems. See deta ...

  5. Android集成高德地图如何自定义marker

    高德地图自定义Marker 高德地图默认的marker样式是这种 一般的修改样式是通过icon接口来调整 MarkerOptions markerOptions = new MarkerOptions ...

  6. ubuntu for windows10设置中文

    运行 sudo dpkg-reconfigure locales ,第一个界面是选择区域,找到后面的zh_CN.UTF-8 UTF-8,回车确认,第二个界面是选择语言,选择zh_CN.UTF-8,回车 ...

  7. Python与数据结构[0] -> 链表/LinkedList[0] -> 单链表与带表头单链表的 Python 实现

    单链表 / Linked List 目录 单链表 带表头单链表 链表是一种基本的线性数据结构,在C语言中,这种数据结构通过指针实现,由于存储空间不要求连续性,因此插入和删除操作将变得十分快速.下面将利 ...

  8. FZU-2216 The Longest Straight(尺取法)

     Problem 2216 The Longest Straight Accept: 523    Submit: 1663Time Limit: 1000 mSec    Memory Limit ...

  9. 洛谷—— P1680 奇怪的分组

    https://www.luogu.org/problemnew/show/1680 题目背景 终于解出了dm同学的难题,dm同学同意帮v神联络.可dm同学有个习惯,就是联络同学的时候喜欢分组联络,而 ...

  10. shell spool

    If you wish to use SQL*Plus Command-line , you'll simply issue the sqlplus command from your shell: ...