C++之 “引用”

“引用”用我们那的话叫 reference

在搜狗百科上是这么解释的:
     写文章时,有意引用 成语、 诗句、 格言、典故等, 以表达自己想要表达的思想感情,说明自己对新问题新道理的见解,这种 修辞手法叫引用。

当然我们今天要讲的不是这样的引用,讲的是C++语法上的引用。

在C++的百度百科上是这么解释的:
     引用引入了对象的一个同义词。 引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。定义引用的表示方法与定义指针相似。

简而言之 引用不是定义一个新的变量,而是给一个已经定义的变量重新起一个别名。

引用的声明方法:类型 &引用名=目标变量名;
    int a=2;
    int &ra=a;

a为目标原名称,ra为目标引用名。给ra赋值:ra=1; 等价于 a=1;

引用的特点:

1. 一个变量可取多个别名
2. 引用必须初始化
3. 引用只能在初始化的时候引用一次,不能改变为再引用其他的变量。
4. 引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。
5. 引用地址。&ra与&a相等,同一块内存空间。即我们常说引用名是目标变量名的一个别名。别名一词好像是说引用不占据任何内存空间。    但是编译器在一般将其实现为const指针,即指向位置不可变的指针。即引用实际上与一般指针同样占用内存。

代码块:

#include<stdio.h>
#include<iostream>
using namespace std;
void Test()
{
 int a = 1;
 int& b = a;                                //占用同一块内存空间
 cout << "a:address->" << &a << endl;
 cout << "b:address->" << &b << endl;
 a = 2;                                    //给a赋值,b一样改变
 cout << "a--->" << a;
 cout << " b--->" << b << endl;
 b = 3;
 cout << "a--->" << a;
 cout << " b--->" << b << endl;
 int& c = b;                                 // 引用一个引用变量,别名的别名
 c = 4;
 cout << "a--->" << a ;
 cout << " b--->" << b ;
 cout << " c--->" << c << endl;
}
int main()
{
 Test();
 system("pause");
 return 0;
}
运行结果:

const做引用
void Test1()
{
 int d1 = 4;
 const int & d2 = d1;                  //声明为const常量
 cout << "d1--->" << d1;
 cout << "  d2--->" << d2 << endl;
 d1 = 5;                               // d1改变 d2的值也会改变。
 //d2 = 6;                             // 不能给常量(不能被修改的量)赋值
 cout << "d1--->" << d1;
 cout << "  d2--->" << d2 << endl;
 const int d3 = 1;
 const int & d4 = d3;                  //类型相同
 //int&d5 = d3;                        //类型不匹配
 cout << "d3--->" << d3;
 cout << "  d4--->" << d4 << endl;
 const int & d6 = 5;                   // 常量具有常性,只有常引用可以引用常量
 double d7 = 1.1;
 //int& d8 = d7;                       //d7是double类型,d8是int
 const int& d9 = d7;                   //d9为int型,不能完全赋值
 cout << "d7--->" << d7;
 cout << " d9--->" << d9 << endl;
}

int main()
{
 Test1();
 system("pause");
 return 0;
}
运行结果:


引用做参数
传统的c语言中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。
所以如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。
But,现在引用的出现完全解决了这一垄断的局面。    请看  ...

Example:交换两个数

1.传统的指针做参数
void swap1(int *a,int *b)
{
   int temp;
   temp=*a;
   *a=*b;
   *b=temp;
}
2.引用做参数
void swap(int &a,int &b)
{
   int temp;
   temp=a;
   a=b;
   b=temp;
}
int main()
{
 int x = 2;
 int y = 4;
 cout << "x=" << x << "  ""y=" << y << endl;
 swap(x,y);
 cout << "x=" << x << "  ""y=" << y << endl;
 system("pause");
 return 0;
}

运行结果:

优点:
引用传递函数的参数,能保证参数传递中不产生临时变量,提高传递的效率,且通过const的使用,保证了引用传递的安全性。

引用做返回值
 
 
int& func(int& x)
{
	int i = 0;
	for (; i < 10; i++)
	{
		x++;
	}
	return x;
}
int main()
{
	int x = 32;
	func(x);
	cout << "x=" << x << endl;
	system("pause");
	return 0;
}

运行结果:
引用作为返回值 一些规则:
  (1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁。
  (2)不能返回函数内部new分配的内存的引用。可能会造成内存泄漏等问题。
  (3)可以返回类成员的引用,但最好是const。
      (4)引用作为函数返回值,这个值的生命周期一定比函数长

通过反汇编看引用

 
 

void func(int& x){ x++;}

反汇编:
void func(int& x)
{
009E4B80  push        ebp  
009E4B81  mov         ebp,esp  
009E4B83  sub         esp,0C0h            //记住这个0C0h,化成十进制为192
009E4B89  push        ebx                 //寄存器的入栈
009E4B8A  push        esi  
009E4B8B  push        edi  
009E4B8C  lea         edi,[ebp-0C0h]      //扩展新栈帧,将有效地址传给edi寄存器,即取偏移地址  
009E4B92  mov         ecx,30h             //4*30h即4*48=192
009E4B97  mov         eax,0CCCCCCCCh      //初始化,未初始化则为烫烫烫烫....
009E4B9C  rep stos    dword ptr es:[edi]  //rep指令:重复上面的指令,ecx的值是重复次数;
                                          //stos指令:将eax的值拷贝esp中(即edi指向的地址)  
  x++;
009E4B9E  mov         eax,dword ptr [x]   //局部变量x的创建,dword 通过指针赋值,ptr就是指针,相当于把x赋值给eax寄存器 
009E4BA1  mov         ecx,dword ptr [eax]  
009E4BA3  add         ecx,1               //x佳佳
009E4BA6  mov         edx,dword ptr [x]  
009E4BA9  mov         dword ptr [edx],ecx  
}

通过查看反汇编我们看见:
        从底层来说,引用的实质是指针,但是---从高层语言级别来看,我们不能说引用就是指针,他们是两个完全不同的概念。我们可以这么说:从语言级别上,指针和引用没有关系,引用就是对象。不是指向对象的指针,也不是对象的拷贝,就是对象!!!

引用和指针异同点:

相同:
在底层实现方式相同,都是指针方式实现

区别:
1.引用只能在定义时初始化一次,之后不能改变指向其它变量(从一而终);指针变量的值可变
2.引用必须指向有效的变量,指针可以为空。
3.sizeof指针对象和引用对象的意义不一样。sizeof引用得到的是所指向的变量的大小,而sizeof指针是对象地址的大小。
4.指针和引用自增(++)自减(--)意义不一样。
5.有多级指针,没有多级引用
6.相对而言,引用比指针更安全

猜你喜欢

转载自blog.csdn.net/komacc/article/details/80138637