歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C++拾遺--引用(左值引用、右值引用)

C++拾遺--引用(左值引用、右值引用)

日期:2017/3/1 9:32:07   编辑:Linux編程

前言

引用就是別名(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成長之路(十):其他高級議題

Copyright © Linux教程網 All Rights Reserved