引用类型

创建引用变量
引用是C++新增的特性,它能实现在函数调用指针能实现的功能,即通过修改参数的值从而修改实参的值。创建引用的语句:
	int a = 1;
	int &b = a;

&在这里不是取地址的意思,而是类型标识符的一部分。表示变量b是一个引用。这样声明的结果是a和b指向相同的内存单元,即b是a的别名。两者完全等效。另外,引用变量必须初始化。
	int a = 1;
	int &b = a;  //初始化b为指向a的引用
	int c = 2;  
	b = c;  //把c赋值给b,编译并没有报错,但实际上这样操作的结果是a和b同时变成了2,
	        //因为a和b其实是等价的,这条语句等价与a=c,即当引用变量初始化之后,不能再将它指向另一个变量

将引用作为函数的参数
前面说到了,将引用作为函数的参数,可以通过修改形参的值,从而改变实参的值。这在试图想使用这种方法的时候是很有效的,至少表示法没指针那么复杂。在不打算修改实参的值的时候,也可以使用引用参数。若不是引用参数时,调用函数的时候系统将会创建相应的临时变量,并将实参的值拷贝进来,函数里将使用的是这些临时变量。如果用引用参数,将不需要这些时间上和空间上的开销,而且声明参数为const也能保证不修改实参的值。因此在不试图修改实参的值的情况下,若参数为结构或类对象,则一般使用const引用参数,若为基本类型,则可以按值传递。
void swap(int &a, int &b)  //参数为引用,可以通过修改形参从而修改实参
{
	int m;
	m = a;
	a = b;
	b = m;
}
引用的特别之处
#include<iostream>
#include<cstdio>
using namespace std;

void fun(int &a)
{
	cout << a << endl;
}

int main()
{
	int a = 1;
	fun(a);
	fun(a + 1);  //编译会报错,因为a+1并不代表某个内存单元(在早期C++是允许的)只有在函数定义参数时声明const,才可以

	return 0;
}

如果函数的参数是引用类型的,当调用函数的实参的类型不正确,或者说正确但不是左值(左值是指能被赋值的元素,如上a+1就不是左值,不能把具体的值赋给a+1,因为a+1并不代表某个内存单元),编译器会报错,只有在形参声明时加const,才能通过编译
void fun(const int &a)
{
	cout << a << endl;
}
加上const之后,当实参类型不正确或者另外一种情况时,编译器将创建相应的临时变量,并把它们初始化成相应的实参的值,并让形参来引用这些临时变量,const表示禁止修改这些临时变量,函数返回后,这些临时变量将不再存在。因此在函数里用到的其实是这些临时变量的值。这最终的效果其实类似于按值传递。
此外C++11还新增了右值引用,即可以引用右值(不能被赋值的元素,比如表达式),用两个&定义右值引用
	int &&b = 1 + 1;
	cout << b << endl;
函数返回引用
#include<iostream>
#include<cstdio>
using namespace std;

int fun1(int a)  //一般情况,函数返回值会被赋值到指定寄存器或者内存中
{                //函数返回后,主函数得从相应的寄存器或者内存中得到返回值
	int c = a*a;  //即需要两次复制操作,即存放返回值和取出返回值
	return c;
}

int &fun2(int a)  //如果返回的是引用,则是直接把返回的引用的值复制到主函数相应的变量中,这里是ans2
{                 //效率稍微高一点
	int c = a*a;
	return c;
}

int main()
{
	int ans1, ans2;  //注意这里接受返回值的都是普通变量,不是引用变量
	ans1 = fun1(2);
	ans2 = fun2(2);

	cout << ans1 << endl << ans2 << endl;

	return 0;
}

如果返回的是引用变量,而且该变量是在函数里创建的局部变量会怎么样呢- -。。
#include<iostream>
#include<cstdio>
using namespace std;

int& fun()  //返回的是函数里创建的局部变量d
{
	int d = 1;
	return d;
}

int main()
{
	int &a = fun();  //两次输出的结果不一样。。。
	a = a + 1;
	cout << &a << endl << a << endl;
	//函数返回d,而a又是引用变量,因此a和d是等价的,地址一样。但d是函数里创建的,函数结束后,d已经失效了!!。。
	//而a的地址又和d一样,那a会怎么样呢。。可以这么理解,把d返回给引用a,则函数结束后,本该失效的d却没失效
	//而是等到第一次把a输出之后才失效。。。。
	cout << &a << endl << a << endl;  //下一次输出,a的值就不确定了,因为它所在的内存块已经被回收了。

	int b = fun();  //如果是普通变量,则不存在这个问题,因为它是把d的值复制给b的,b和d的地址不同
	cout << &b << endl << b << endl;   //两次输出都一样
	cout << &b << endl << b << endl;

	return 0;
}

因此一般返回引用变量,尽量不要返回在函数里创建的局部变量,而是返回引用参数

#include<iostream>
#include<cstdio>
using namespace std;

int& fun(int &a)
{
	return a;
}

int main()
{
	int a = 1;
	int &b = fun(a);
	int c = fun(a);

	cout << &a << " " << a << endl;  //a和b是等价的
	cout << &b << " " << b << endl;
	cout << &c << " " << c << endl;  //c是普通变量,只是值相等,地址不同

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值