Welcome 微信登录
编程资源 图片资源库 蚂蚁家优选 PDF转换器

首页 / 操作系统 / Linux / C++拾遗--引用(左值引用、右值引用)

前言引用就是别名(alias)。所谓别名,就是对已存在的对象另起一个名字。本身含义并不难理解,但与其它概念一组合,就成了使用难点。再加上新标准提出了新的一种引用-右值引用,引用这一概念就变得更加难以理解和使用。正文随着新标准(新标准往往就是新的技术)的提出,引用这一概念分成两类:左值引用、右值引用。其中左值引用是最常用的一种,而右值引用则是语言使用上的一种革新。1.左值引用左值引用的基本语法Type &引用名 = 左值表达式;#include <iostream>
using namespace std;
int main()
{
 int a = 10;
 //ra是a的引用(别名),相当于把ra与a绑定。
 int &ra(a);
 cout << ra << "  " << (void*)&ra << "  " << (void*)&a << endl;
 cin.get();
 return 0;
}运行引用的基本规则
  1. 声明引用的时候必须初始化,且一旦绑定,不可把引用绑定到其他对象。
  2. 对引用的一切操作,就相当于对原对象的操作。
2.右值引用以上是最常见的引用方式,我们称之为左值引用。为了顺利区分左右值引用的概念,我们先来看下左右值的概念。首先,左右值是表达式的属性。何为表达式?表达式由一个或多个运算对象组成。字面值和变量是最简单的表达式。一个对象被用作右值时,使用的是它的内容(值),被当作左值时,使用的是它的地址。int a = 1;a + 1;    //a + 1 是表达式在C++旧标准中,我们可以引用a,但却无法引用a+1,这是为什么呢?这是因为,变量a被创建后,在它的作用域内是一直存在的。如此一来,它的引用是有存在意义的。而a+1不是一个对象,在运算中临时存在于寄存器中,而寄存器中的值是时刻被刷新的,创建a+1的引用显得没有任何意义。为了成功的使用类似于a+1这种右值的引用。C++新标准提出了区别于以往的引用-右值引用。右值引用的基本语法Type &&引用名 = 右值表达式;#include <iostream>
using namespace std;
int main()
{
 int a = 10;
 //右值引用
 int &&ra(a+1);
 cout << ra << ends << (void*)&ra << ends << (void*)&a << endl;
 ra++;
 cout << ra << endl;
 cin.get();
 return 0;
}运行对右值引用的一种可能的内部实现解释int a = 1;int *p = new int(a + 1);int &ra = *p;delete p;      //不再使用引用了,动态内存的释放由C++自动管理其中第二、三两句就对应右值引用:int &&ra(a+1);3.引用作为函数参数引用作为函数参数时,有着指针一样的功能。#include <iostream>
using namespace std;
void fun(int &ra)
{
 cout << ra << ends << (void*)&ra << endl;
 ra++;
}
int main()
{
 int a = 10;
 fun(a);
 cout << a << ends << (void*)&a << endl;
 cin.get();
 return 0;
}运行在函数fun内,对形参ra的值,做出了更改,这一操作影响了实参a。显然引用的使用比指针简单。4.引用与数组int a[]{1, 2, 3, 4, 5};int (&ra)[5] = a;   //对数组进行引用5.引用与指针引用一级指针int a(0), *p = &a;int *&rp = p;引用二级指针int a(0), *p = &a;int **pp = &p;int **&rp = pp; //引用二级指针,若编译不通过,使用 int (**(&rp)) = pp;6.引用与函数指针#include <iostream>
using namespace std;
int add(int a, int b)
{
 return a + b;
}
int sub(int a, int b)
{
 return a - b;
}
int mul(int a, int b)
{
 return a * b;
}
int divi(int a, int b)
{
 if (b)
  return a / b;
 else
  return INFINITY;
}
int main()
{
 int a(100), b(10);
 cout << "使用函数名" << endl;
 cout << add(a, b) << ends << sub(a, b) << ends << mul(a, b) << ends << divi(a, b) << endl;
 //padd是函数指针
 int(*pfun)(int, int);
 cout << "使用函数指针" << endl;
 pfun = add;
 cout << pfun(a, b) << ends;
 pfun = sub;
 cout << pfun(a, b) << ends;
 pfun = mul;
 cout << pfun(a, b) << ends;
 pfun = divi;
 cout << pfun(a, b) << endl;
 //函数指针数组
 int(*pfuns[])(int, int){add, sub, mul, divi};
 cout << "使用函数指针数组" << endl;
 cout << pfuns[0](a, b) << ends << pfuns[1](a, b) << ends << pfuns[2](a, b) << ends << pfuns[3](a, b) << endl;
 cout << "函数指针的引用" << endl;
 int(*(&rfun0))(int, int)(pfuns[0]);
 int(*(&rfun1))(int, int)(pfuns[1]);
 int(*(&rfun2))(int, int)(pfuns[2]);
 int(*(&rfun3))(int, int)(pfuns[3]);
 cout << rfun0(a, b) << ends << rfun1(a, b) << ends << rfun2(a, b) << ends << rfun3(a, b) << endl;
 cin.get();
 return 0;
}运行------------------------------分割线------------------------------C++ Primer Plus 第6版 中文版 清晰有书签PDF+源代码 http://www.linuxidc.com/Linux/2014-05/101227.htm读C++ Primer 之构造函数陷阱 http://www.linuxidc.com/Linux/2011-08/40176.htm读C++ Primer 之智能指针 http://www.linuxidc.com/Linux/2011-08/40177.htm读C++ Primer 之句柄类 http://www.linuxidc.com/Linux/2011-08/40175.htm将C语言梳理一下,分布在以下10个章节中:
  1. Linux-C成长之路(一):Linux下C编程概要 http://www.linuxidc.com/Linux/2014-05/101242.htm
  2. Linux-C成长之路(二):基本数据类型 http://www.linuxidc.com/Linux/2014-05/101242p2.htm
  3. Linux-C成长之路(三):基本IO函数操作 http://www.linuxidc.com/Linux/2014-05/101242p3.htm
  4. Linux-C成长之路(四):运算符 http://www.linuxidc.com/Linux/2014-05/101242p4.htm
  5. Linux-C成长之路(五):控制流 http://www.linuxidc.com/Linux/2014-05/101242p5.htm
  6. Linux-C成长之路(六):函数要义 http://www.linuxidc.com/Linux/2014-05/101242p6.htm
  7. Linux-C成长之路(七):数组与指针 http://www.linuxidc.com/Linux/2014-05/101242p7.htm
  8. Linux-C成长之路(八):存储类,动态内存 http://www.linuxidc.com/Linux/2014-05/101242p8.htm
  9. Linux-C成长之路(九):复合数据类型 http://www.linuxidc.com/Linux/2014-05/101242p9.htm
  10. Linux-C成长之路(十):其他高级议题
本文永久更新链接地址:http://www.linuxidc.com/Linux/2015-02/114056.htm