c++引用

c++引用

  • 引用的概念:对一个数据可以建立一个“引用”,它的作用是为了一个变量起一个别名。
  int a; //定义a是整形变量
  int &b = a;  // 声明b是a的“引用”

请注意:在上面声明中,&是引用声明符,并不代表地址。在数据类型后面出现的&是运用声明符,在其他场合出现的是地址符。例如:

char &d = c;   //此处的& 是引用声明符
int *p = &a;    //此处的&是地址符

注意:

  1. 引用是一种独立的数据类型,对引用只有声明,没有定义。必须先定义一个变量,然后声明对该变量建立一个引用(别名)。
  2. 声明一个引用时,必须同时使之初始化,即声明它代表哪一个变量。当引用作为函数形参时不必在声明中初始化,它的初始化是在函数调用时的虚实结合体现的,即形参的引用是实参的别名。
  3. 在声明一个引用后,不能再使之作为另一个变量的引用。例如
int a1,a2;
int &b = a1;   //声明b 是a1 的引用(别名)
int &b = a2;  //不合法,b已经为a1的引用,不能再成为另一个变量的引用了。
  1. 不能建立引用数组,例如:
int a[5];
int &b[5]=a;   //错误,不能建立引用数组
int &b=a[0];   //错误,不能引用数组元素的别名。

我们可以这样理解,数组名只有放在sizeof下或者取地址&下,才表示整个数组。在其他情况下都是数组首元素地址。

  1. 不能建立引用的引用,例如:
int a = 3;
int &b = a; //声明b是a的别名
int &c = b; //试图建立引用的引用,错误

也没有引用的指针。

int * p = b;   //不能建立指向引用的指针。
  1. 可以取引用的地址。如果已经声明b是a的引用,则&b就是变量a的地址&a。
int *pt ;
pt = &b ; //把变量a 的地址&a 赋给指针变量pt ,可以。 
  1. 区别引用声明符 & 和地址运算符 &。出现在声明中的 & 是引用声明符,其他情况下的 & 是地址声明运算符。
int &b = a; //声明b是a的引用。
cout<<&b<<endl;   //输出b的地址,此处 &a 不是引用。

二者形式相同,含义不同。在声明了引用之后,在使用它时不带&,而只用引用的名字。

** 内存:如果在程序中声明了b是a的引用,实际上在内存中为b开辟了一个指针型的存储空间,在其中放的是变量a的地址,输出引用b时,就输出b所指向的变量a值,相当于 *b ,引用其实就是一个指针常量,它的指向不能改变,之能指向一个指定的变量。所以引用的的本质还是指针,所有引用的功能可以由指针实现。 **

引用作为函数的参数

这时我们比较一下c语言中对于函数的形参实参的传递方式。总共有两种方式。一种传值调用,一种是传地址。

  1. 我们很熟悉的传值调用函数,例如:
void Sawp(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}

int main()
{
	int x=1;
	int y=2;
	Swap(x,y);
	return 0;
}
  • 上面的代码明显不能完成调换的要求。执行完之后,x和y的值并没有发生改变。这是因为形参只是实参的一份临时拷贝。Swap函数中变的只是栈上空间的值,所以不能实参的值。
  1. 传值中传递指针类型的实参。
Swap(int* a, int* b)
{
   int temp = *a;
   *a = *b;
   *b = temp;
}
int main()
{
   int x = 1;
   int y = 2;
   Swap(&x , &y);
   return 0;
}
  • 这种虚实结合的方式任然是“值传递”的方式,只是实参的值是变量的地址而已。通过形参指针变量访问主函数中变量x,y。并改变他们的值。
  1. 以引用作为形参,在虚实结合时建立变量的引用,使形参名作为实参的“引用”,即形参成为实参的引用。
void Swap(int &a, int &b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int x = 1;
	int y = 2;
	Swap(x , y);
	return  0;
}
  • 这就是传地址的方式。此时虽然传的是变量x,y,但是形参拿到的却是x,y变量的地址。

还有一些引用的一些小知识

  • 常引用
void TestConstRef()
{
const int a = 10;
//int& ra = a; // 该语句编译时会出错,a为常量
const int& ra = a;
// int& b = 10; // 该语句编译时会出错,b为常量
const int& b = 10;
double d = 12.34;
//int& rd = d; // 该语句编译时会出错,类型不同
const int& rd = d;
}

这里面牵扯到一些关于类型转换相关的东西。我重点说一下最后一句,double b = 3.14; const int& rd = b; 这句中,不同类型的引用。其中先定义一个变量b,然后建立引用时,先将double型的 b 复制一份,将其强制转换成 int 型,然后拿到这个地址给引用rd。一般也不常用。所以大家了解一下就好。

  • 不能返回栈空间上的引用,和一般的返回栈上面的值一样。函数调用结束完了之后,栈上的内存会清空。所以拿不到栈空间的变量或者引用。
  • 指针和引用在传参的效率上基本上是一样的。

我这里罗列引用和指针的区别

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  3. 没有NULL引用,但有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全

关于引用的一些知识我就总结这么多,日后学到,再更新,如有其它见解,欢饮下方讨论。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值