c++之引用 &

**

c++中的引用是c++与c不同的一个地方,也是c所没有的。**

什么是引用?

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

举个例子:

王小明是一个人,“王小明”就是他的名字,但是在家他妈可能会叫他 “小明”,这个 “小明” 就相当于一个别名,也就是引用。

基本语法:

类型 & 引用变量名(对象名) = 引用实体。

int main() {
	int a = 10;
	int& ra = a; // 定义引用类型
	//ra就是a的引用 , 也就是a的别名。

	cout << "a的地址:" << &a << endl;
	cout << "ra的地址:" << &ra << endl;


	return 0;
}

在这里插入图片描述

这也印证了编译器并没有为ra单独开辟空间,而是用和a一样的空间。

引用的特性

1.引用在定义时必须初始化

int a = 10;
	int& ra ; //这是不被允许的!

2.一个变量可以有多个引用
相当于你可以有很多个外号,别名,不冲突.

3 引用一旦引用一个实体,再不能引用其他实体!

int main() {
	int a = 10;
	int& ra = a; // 定义引用类型
	//ra就是a的引用 , 也就是a的别名。
	int b = 20;
	// &ra = b; 这是不被允许的
	ra = b; // 相当于将b的值赋给 ra 也就是 a


	return 0;
}

常引用:

int main() {
	const int a = 10;
	int& ra = a; //该语句编译时会报错

	 return 0;
}
int main() {
	const int a = 10;
	
	const int& ra = a;
    //这样是没问题的


	 return 0;
}
int main() {
	double a = 1.22;
	
	int& ra = a;
    //这样也会报错,a为double,b为int,无法修改a的值
	 return 0;
}
int main() {
	double a = 1.22;
	
	int& ra = 10;//会报错,引用常数10,但是10不可修改的
    

	 return 0;
}
int main() {
	double a = 1.22;
	
	const int& ra = 10; //不会报错
    const int& rra =a ;//也不会报错



	 return 0;
}

总结:

1.const 会改变变量权限,将原来的变量又 可读可写 变为 只能读不能写。
2.当引用变量与原变量不同,或引用了常数时,应当加上const,因为改变量是不可写的。
3.对原引用变量,权限只能缩小,不能放大。

使用场景:

1.做函数的参数:
void swap(int& x, int& y) {
	int tmp = x;
	x = y;
	y = tmp;

}




int main() {
	
	int x = 10;
	int y = 20;
	swap(x, y);
	cout << "x:" << x << endl;
	cout << "y:" << y << endl;


	 return 0;
}

在这里插入图片描述

这里我们不需要指针就完成了两个变量的交换。

void swap(double& x, double& y) {
	double tmp = x;
	x = y;
	y = tmp;
}

因为c++支持函数的重载,配合引用,让我们更加方便。

2.做返回值

int count() {
	int n = 0;
	++n;
	return n;


}



int main() {
	
	int ret = count();
	cout << "ret:" << ret << endl; // ret : 1;



	 return 0;
}

当函数返回值时,该返回值会被储存在一个临时变量中。

int count() {
	int n = 0;
	++n;
	return n;


}



int main() {
	
	const int& ret = count(); // 前面一定要const, 因为count()的返回值储存在一个临时变量里,临时变量具有常性,无法修改。!

	cout <<  ret << endl; // 


	 return 0;
}
int& count() {
	int n = 0;
	++n;
	return n;


}



int main() {
	
	 int& ret = count();

	cout <<  ret << endl; // ret 的值是1 
	cout << " " << endl; //
	cout << ret << endl; //ret是随机值
	

	 return 0;
}

由上述代码我们可以得知,当你的函数返回值是引用返回时,是没有临时变量的,此时你的ret有点类似与野指针了,count()的那块空间已经还给内存了,但是为什么会有一个是1 一个是随机值的情况呢?
其实是这样的:再执行完语句 int& ret = count(); 后,count函数的函数栈帧已经还给内存,但是此时没有其他函数覆盖该空间,所以ret的值仍然是1,但是 当执行了语句 cout << " " << endl; 后, cout会覆盖原来的函数栈帧,让ret变为随机值

int& count() {
	static int n = 0;
	++n;
	return n;


}



int main() {
	
	 int& ret = count();

	cout <<  ret << endl; // ret 的值是1 
	
	

	 return 0;
}

但当n变为static修饰的静态变量时,引用传值就不会出现上述的问题。

注意: 如果函数返回时,出了函数作用域,如果返回对象还未还给系统,则可以使用引用返回,如果已经还给系统了,则必须使用传值返回!

传值,传引用效率的比较

简单一句话:传值效率比传引用效率低,且数据量越大越明显

引用和指针的区别:

1 引用定义时必须初始化,指针不一定。
2 引用在初始化一个实体后,就再也不能引用其他实体,而指针可以在任何时候指向
任何一个同类型的实体

3 没有NULL引用,只有NULL指针
4在sizeof中,引用为引用类型的大小,而指针大小永远都是地址空间所占字节数(32为平台 4字节)
5有多级指针,但没有多级引用
6引用比指针更加安全

注意: 引用和指针在底层的实现上是一样的,引用时按照指针方式来实现的。
(可以参考他们的汇编代码)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值