引用的全面理解

来源:互联网 发布:jquery 1.7.1.min.js 编辑:程序博客网 时间:2024/06/04 19:22

什么是引用?

引用是在C++2.0版本引入的。

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量一直绑定在一起共用同一块内存空间。

一般情况,引用具有以下性质。

  • 1.引用不是一个变量,只是一个已存在变量的别名。
int a = 10;  int& ra = a;//ra是a的引用  //sizeof(ra) == sizeof(a)  ra = 20;//对ra操作赋值,则相当于对a赋值。  
  • 2.可以有多个引用与同一个已存在变量绑定到一起。
int a = 10;  int& ra1 = a;  int& ra2 = a;  int& ra3 = a;//ra1,ra2,ra3都是a的别名  
  • 3.引用不是一个变量,不能定义引用的引用,不能定义指向引用的指针
int& rra = ra;//错误。  int *p = ra;//错误  
  • 4.由于要和某一变量绑定,所以引用必须初始化。
int& ra;// error C2530: “ra”: 必须初始化引用  
  • 5.引用的类型要和与之绑定的变量类型严格匹配。
int a = 10;  float& fa = a;//error C2440: “初始化”: 无法从“int”转换为“float &”  
  • 6.引用绑定后,将一直与变量绑定在一起,所以引用不能再重新绑定到另一变量。
int a = 10;  int b = 20;  int& ra = a;  &ra = b;//错误,无法重新绑定  

注:数组可以引用,只是写法和一般不同

int b[10] = {0};  int (&rb)[10] = b;  

Const的引用

引用除了可以和变量绑定外,还可以绑定到const对象上,称之为“对常量的引用”。所以,对常量的引用,不能修改它所绑定的对象。

提示:常量引用是其实对const的引用,因为引用本身不是一个对象。

const int a = 10;  const int& ra = a;//对const修饰的变量a的引用  ra = 20;//错误,ra试图修改与它绑定对象的值。  int& ra2 = a;//错误,试图让一个非常量引用绑定到一个常量上。  

前面提到,引用的类型必须和其绑定对象的类型一致,但是,C++允许一个常量引用绑定到非常量的对象、字面值,甚至是一个表达式。

int a = 10;  const int b = 20;  const int& ra = a;//允许将const int&绑定到一个普通int对象上  const int& rb = b;//rb是一个常量引用。  const int& r1 = ra*rb;//r1是一个常量引用  int& r2 = r1*3;//错误:r2是一个非常量引用。  

为什么会出现上面的特例呢?
观察下列代码,判断编译器对于i1和i2的理解。

double d = 20.0; int& i1 = d;//error C2440: “初始化”:
无法从“double”转换为“int &” const int& i2 = d;//warning C4244: “初始化”:
从“double”转换到“constint”,可能丢失数据


分析:

第一句话,错误提示:无法从double转换为int &,我们都理解,是因为类型不同。

但是第二句话,不是错误提示:无法从double转换为const int &呢?确实警告double转换为const int有数据丢失。

说明,编译器帮我做了隐式转化,将double转化为const int,然后等号左右两类型相同,自然通过编译。

转化过程:这里编译器对代码进行插手了,为了确保让i2绑定到一个整型,编译器隐式转化,用double类型d 生成了一个临时对象const
int,(临时对象具有常性)。将r2指向了临时对象。

对const的引用可能引用一个非const对象。此时可以通过特殊手段改变const引用的值。

int a = 10;  const int& ra1 = a;//常量引用  int& ra2 = a;//非常量引用  ra1 = 20;//错误,无法修改  ra2 = 20;//正确,可以修改  

引用作为参数或返回值

对引用的操作就是对其绑定对象的操作,所以引用可以作为参数或返回值。

引用作为参数和返回值具有和指针一样的效率但是比指针更安全,操作更方便。

原因下面描述。

引用和指针的区别

想到搞清楚引用与指针的区别,要先看看编译器是如何看待他俩的工作原理

#include <iostream>  int main()  {      int a = 10;      int& ra = a;      int* pa = &a;      return 0;  }  

看其汇编

    int& ra = a;  012D13C5  lea         eax,[a]   012D13C8  mov         dword ptr [ra],eax       int* pa = &a;  012D13CB  lea         eax,[a]   012D13CE  mov         dword ptr [pa],eax   

可以发现,编译器对指针和引用的看待方式相同,即引用被当做指针来看待。 所以:我们一般将int& ra = a与nt *const ra =
a;是等效的。

虽然两者在底层上的实现是相同的,都是当做指针来使用。

但是,在语言层面两者还是有很大的不同。

根据对引用的描述和指针的概念比较可以的出以下结论

  • 1、引用在定义时必须初始化,指针没有要求。

  • 2、一旦一个引用被初始化为指向一个对象,就不能再指向其他对象,而指针可以在任何时候指向任何一个同类型对象

  • 3、没有NULL引用,但有NULL指针。

  • 4、在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数。

  • 5、引用自加改变变量的内容,指针自加改变了指针指向

  • 6、有多级指针,但是没有多级引用

  • 7、引用比指针使用起来相对更安全
    转自
    http://blog.csdn.net/qq_35524916/article/details/68239867

0 0