C++的引用

 1.引用的使用

1.作用:给变量起别名,本质就是名字起一个别名,但是指向同一个地址。别名与原名的数据类型必须一样。

2.语法:数据类型 &别名 = 原名 (int & b =a)

下面就用一个实列来说明

#include <iostream>
using namespace std;

int main()
{
	// 数据类型 &别名 = 原名
	int a = 10;
	int& b = a; // 创建引用给a的地址再起一个名字b,因此a与b都指向同一块内存
	cout << "a = " << a <<endl;
	cout << "b = " << b <<endl;
	system("pause");
	return 0;
}

我们会发现,打印出来的a与b都是10。

通过修改b也可以修改a的值,本质就是同一个地址,两个名字都可以访问

#include <iostream>
using namespace std;

int main()
{
	// 数据类型 &别名 = 原名
	int a = 10;
	int& b = a; // 创建引用给a的地址再起一个名字b,因此a与b都指向同一块内存
	b = 100;
	cout << "a = " << a <<endl;
	cout << "b = " << b <<endl;
	system("pause");
	return 0;
}

我们发现a与b的输出都改为了100。

3.引用的注意事项

 第一点就是引用必须初始化,下面这样定义是错误的,必须初始化。

int& c; // 错误的

这样是正确的,吧b初始化,表示b是a的别名,a与b都指向同一段内存。

	int a = 10;
	int& b = a; 

第二点是引用在初始化后,不可以改变。

 如果改成b=c,这个就是赋值操作,吧c里面的100赋值给b,打印后发现a与b都是100了.

b=c// 是赋值操作不是修改引用。

2.引用做函数参数

对于做函数的参数,函数传参时,有三种,一种是值传递,一种是地址传递,还有一种是传递引用。

1.作用:函数传参时,可以利用引用的计数让形参修饰实参

2.优点:可以简化指针修改实参

下面就介绍一下三种函数参数的区别


#include <iostream>
using namespace std;

// 1.  值传递 形参不会修饰实参,即main里面的a与b值不会改变
void mtSwap0(int a,int b) 
{
	int temp = a;    // 在这里交换的是形参里面的a与b而不是实参里面的a与b,因此main里面的a与b没                
	a = b;           //有改变,本质其实是四个个变量的地址不同
	b = temp;
}
// 2.  地址传递 形参会修饰实参,即main里面的a与b值会改变
void mySwap1(int* a,int* b) //这里的a与b就是实参里面的a与b只是起一个别名但是地址都一样
{
	int temp = *a; //因为之间传递的是地址,因此在这里交换,main里面的也得到了交换
	*a = *b;    // *a是取a里面的地址*b是取b里面的地址,这句就是把b地址里面的值赋给a地址里面的值
	*b = temp;
}
// 3. 引用传递 形参会修饰实参,即main里面的a与b值会改变
void mySwap2(int& a,int& b)
{
	int temp = a;  //引用是起别名,但本质是操作main函数里面的地址通过起别名来操作main里面的值
	a = b;
	b = temp;
}
int main()
{
	int a = 10;
	int b = 20;

	// mtSwap0(a, b);   //发现a与b值没有交换,因此值传递 形参不会修饰实参
	// mySwap1(&a, &b);    //发现a与b值交换,因此地址传递 形参会修饰实参
	mySwap2(a, b);      //引用即&c = a表示 a与c同一个地址   发现a与b值交换,因此引用传递 形参会修饰实参

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;

	return 0;
}

总结:通过引用参数产生的效果与按指针传递是一样的,引用的语法更加清晰。

3.引用做函数的返回值

1.不要返回局部变量的引用。

因为局部变量属于栈区,属于改函数执行完后,改内存被编译器直接释放,数据就消失了。

通过以下案例展示

#include <iostream>
using namespace std;
int& ceshi()
{
	int a = 10;
	return a;
}
int main()
{
	int& reference = ceshi();
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;
	system("pause");
	return 0;
}

结果显示第一次打印是正常的,那是因为编译器做了保留,还没来得及释放这个内存

第二次打印就是乱码,表示编译器已经把局部变量a的地址释放。 

解决方法是可以在 int a前面加static把局部变量改为全局变量,这样在执行完函数后,a的内存就不会被释放了,因为他是静态变量放在全局区,这里的数据是在程序结束后系统自己释放。对于内存的那个区可以在我的其他文章详细看一下。

代码测试

#include <iostream>
using namespace std;
int& ceshi()
{
	static int a = 10;
	return a;
}
int main()
{
	int& reference = ceshi();
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;

	system("pause");
	return 0;
}

发现打印的结果都是10没有出现上面的第二次之后乱码。

总结:不能返回局部变量的引用,要想返回就在数据类型前面加static改为静态变量。

2.函数的调用可以作为左值。

#include <iostream>
using namespace std;
int& ceshi()
{
	static int a = 10;
	return a;  //这里的a是原名
}
int main()
{
	int& reference = ceshi();   // 通过这句给a起别名 别名叫reference
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;

	ceshi() = 1000;  //这句相当于给a赋值1000,ceshi()这个函数返回的就是a,等价于a = 1000
	 
	cout << "reference = " << reference << endl;
	cout << "reference = " << reference << endl;

	system("pause");
	return 0;
}

通过上面代码我们发现

前两次打印10,后面两次打印1000,这个原因是首先我们通过 

int& reference = ceshi(); 

这句代码给变量a起了一个别名叫reference,因为变量a用static声明了因此是一个全局区的变量。在程序运行完后,系统自动释放改空间。

通过打印我们可以看出reference是等于10的。

ceshi() = 1000;

这句就是函数的调用可以作为左值,因为ceshi()返回的是变量a,那么就是a = 1000,

又因为reference 是a的别名,两个是一个内存,因此在后面两次打印reference的值的时候就是1000了。

总结:如果函数的返回值是引用,那么这个函数的调用可以作为左值。

左值就是在等号左边的东西(如 a=10,那么a就是左值)。

4.引用的本质

引用的本质在c++里面就是在内部实现一个指针常量

指针常量是什么如果不清楚可以在我前面的文章查看,就是指针的指向不可以修改,指向的值可以修改。

int& ref = a;  就等于 int* const ref = &a;就是指针常量,即指针的指向不可以修改

ref = 20;  内部ref就是解引用,即 *ref =20 ;只不过我们使用int& ref这样的话编译器就自动帮我们转换了。直接ref = 20就可以了,而不用*ref = 20;

下面就是实列

#include <iostream>
using namespace std;
// 引用本质就是 int* const ref = &a    int& ref = a;
void func(int& ref)
{
	ref = 100;  // ref是引用 本质是 *ref = 100
}
int main()
{
	int a = 10;
	int& ref = a;  // 本质就是 int* const ref = &a指针指向不可以修改,值可以修改  
	ref = 20; //  本质就是 *ref = 20 ;

	cout << "a = " << a << endl;
	cout << "ref = " << ref << endl;
	func(a);
	system("pause");
	return 0;
}

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值