复习:C/C++中的引用

一、引用

引用本质上是一个指针常量,在内存中为引用开辟了一个指针型的内存单元。

1.在引用的使用中,单纯给某个变量去别名是毫无意义的,引用的目的主要用于在函数参数的传递中,解决大块数据或对象的传递效率和空间不如意的问题

2.用引用传递函数的参数,能保证参数在传递的过程中不产生副本,从而提高传递效率,同时通过const的使用,还可以保证参数在传递过程中的安全性

3.引用本身是目标变量或对象的别名(查看符号表,引用与对象名都对应同一个地址),对引用的操作本质上就是对目标变量或对象的操作。因此能使用引用时尽量使用引用而非指针

1、引用的特点:

(1)、声明引用时必须初始化:

int a; //声明变量a
int& ra = a; //声明一个引用,名字是ra,ra引用了a
int& b;//这是非法的,b不知道它引用了谁

(2)、引用一旦声明,便不能转移或修改了:

int a, b; //声明变量
int& ra = a; //声明一个引用,名字是ra,ra引用了a
ra = b;//这是非法的,ra已经引用了b

或许正是因为以上的特点,才会说引用比指针更安全了。

2、引用的应用场景:

作为函数参数以及从函数中返回值。

(1)、引用作参数

a、传递可变参数

传统的c中,函数在调用时参数是通过值来传递的,这就是说函数的参数不具备返回值的能力。所以在传统的c中,如果需要函数的参数具有返回值的能力,往往是通过指针来实现的。比如,实现两整数变量值交换的c程序如下:

/* 通过传入参数地址的方式修改并返回参数 */
void swapint(int *a,int *b){
	int temp;
	temp=*a;
	a=*b;
	*b=temp;
}

使用引用机制后,以上程序的c++版本为:

/* 
int x,y;
swapint(x,y); 
*/
void swapint(int &a,int &b){
	int temp;
	temp=a;
	a=b;
	b=temp;
}

b、给函数传递大型对象
当大型对象被传递给函数时,使用引用参数可使参数传递效率得到提高,因为引用并不产生对象的副本,也就是参数传递时,对象无须复制。下面的例子定义了一个有限整数集合的类:

const maxCard=100;
Class Set{
int elems[maxCard]; // 集和中的元素,maxCard 表示集合中元素个数的最大值。
int card; // 集合中元素的个数。
public:
Set () {card=0;} //构造函数
friend Set operator * (Set ,Set ) ; //重载运算符号*,用于计算集合的交集,用对象作为传值参数
// friend Set operator * (Set & ,Set & ) 重载运算符号*,用于计算集合的交集,用对象的引用作为传值参数
...
}

Set operator *( Set Set1,Set Set2){
	Set res;
	for(int i=0;i<Set1.card;++i){
		for(int j=0;j>Set2.card;++j){
			if(Set1.elems[i]==Set2.elems[j]){
				res.elems[res.card++]=Set1.elems[i];
				break;
			}
		}
	}
	return res;
}

由于重载运算符不能对指针单独操作,我们必须把运算数声明为 Set 类型而不是 Set * 。每次使用*做交集运算时,整个集合都被复制,这样效率很低。我们可以用引用来避免这种情况。

Set operator *( Set &Set1,Set &Set2){ 
	Set res;
	for(int i=0;i<Set1.card;++i){
		for(int j=0;j>Set2.card;++j){
			if(Set1.elems[i]==Set2.elems[j]){
			res.elems[res.card++]=Set1.elems[i];
			break;
			}
		}
	}
	return res;
}
(2)、引用作返回值

用引用作函数的返回值时与作参数时的作用类似,在内存中也不产生返回值的副本
引用能做返回值的2种情况:

  • 返回的引用是传入参数列表中的引用
  • 返回的引用是全局变量的引用。因为局部变量在函数结束时也跟着消逝。

a、返回的引用是全局变量的引用。可节省临时变量,提高效率。

/* 必须是全局变量。因为局部变量在函数结束时也跟着消逝。 */
float temp;
float &fn(void){ //&说明返回的是temp的引用,换句话说就是返回temp本身
    return temp;
}
float fn_simple(void){ //非引用返回值的函数
    return temp;
}
int main(){
	float &a = fn();	//相当于 float &a = temp
	float b = fn();		//相当于 float b = temp
	float c = fn_simple();
	/* 相当于temp-->栈中某临时变量-->b ,多了个中间商 */
}

b、返回的引用是传入参数的引用。可直接对函数进行赋值(第一次见到这种操作)
如果一个函数返回了引用,那么该函数的调用也可以被赋值。下面的例子:max(x,y)+=1.0;

double &max(double &d1,double &d2){
	return d1>d2?d1:d2;
}
int main(){
	double x=1.0,y=2.0;
	max(x,y)+=1.0;
	/* 结果x=1.0,y=3.0 */
}

3、C/C++ 中指针和引用的区别?

从编译的角度来讲,程序在编译时分别将指针和引用添加到符号表上,符号表中记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值(与实参名字不同,地址相同)。符号表生成之后就不会再改,因此指针可以改变其指向的对象(指针变量中的值可以改),而引用对象则不能修改。
所以,可以推断:sizeof (引用),得到的是所指向变量的大小;sizeof (指针),得到的是指针的大小;

1.指针有自己的一块空间,而引用只是一个别名;

2.使用sizeof看一个指针的大小是4,而引用则是被引用对象的大小;

3.指针可以被初始化为NULL,而引用必须被初始化且必须是一个已有对象 的引用;

4.作为参数传递时,指针需要被解引用才可以对对象进行操作,而直接对引 用的修改都会改变引用所指向的对象;

5.指针在使用中可以指向其它对象,但是引用只能是一个对象的引用,不能 被改变;

6.指针可以有多级指针(**p),而引用没有;

7.指针和引用使用++运算符的意义不一样;

8.如果返回动态内存分配的对象或者内存,必须使用指针,引用可能引起内存泄露。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值