c++:引用&是什么?c++引用详解及使用

引用是什么?

引用&就是取别名.
比如齐天大圣是孙悟空的别名,弼马温也是孙悟空的别名.齐天大圣被困在五行山,那么孙悟空有没有被困呢?

#include<iostream>
#include<assert.h>
using namespace std;
int main()
{
	int a = 10;
	int& pa = a;  //pa是a的别名
	pa = 20;

	cout << &a << endl;
	cout << &pa << endl;

	cout << a << endl;
	cout << pa << endl;

	return 0;
}

image.png
我们发现,引用的别名pa和a的地址,值都是一样的.(齐天大圣就是孙悟空)

引用的使用规范

俗话说:行车不规范,亲人两行泪.引用的使用也是必须要遵守规范的.

引用必须初始化

image.png

一个变量可以有多个别名

这个跟我们人一样,可以有多个别名.还可以给别名起别名.比如再给孙悟空的别名齐天大圣起一个别名:猴子.

#include<iostream>
#include<assert.h>
using namespace std;
int main()
{
	int a = 10;
	int& b = a; //b是a的别名
	int& c = b; //c是b的别名,同时也是a的别名
	return 0;
}

引用不能改变指向

这个就好像齐天大圣已经成为孙悟空的别名,不能再被其他人使用.
这个规范是引用和指针之间最大的不同.也是引用无法替代指针的最大原因

#include<iostream>
#include<assert.h>
using namespace std;
int main()
{
	int a = 10;
	int b = 20;

	int& c = b;//c是b的别名
	c = a;  //这个只是把a的值10赋值给c

	cout << &a << endl;
	cout << &b << endl;
	cout << &c << endl;
	return 0;
}

image.png
我们可以看到c的地址没有发生改变. 在这里我们也可以看到祖师爷设计的初衷.如果没有这个语法 c = a这个语句就会有歧义. 到底将a的值赋值给c,还是将c改为a的别名.

引用的使用场景

引用做参数

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}
void Swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
int main()
{
	int x = 19;
	int y = 99;
	Swap(&x, &y);

	cout << "x = " << x << endl;
	cout << "y = " << y << endl;
        
        Swap(x, y);

	cout << "x = " << x << endl;
	cout << "y = " << y << endl;
	return 0;
}

image.png
在我们学引用之前,当我们需要交换两个变量的值时要把变量的地址传过去,在Swap函数里面还要不断地解引用,多麻烦.
现在只需要传x和y就行.

引用做返回值

class Stack
{
private:
	int* _a;
	int _size;
	int _capacity;
public:
	void Init(int n = 4)
	{
		int* tmp = (int*)malloc(sizeof(int) * n);
		//assert(tmp != nullptr);
		_a = tmp;
		_size = 0;
		_capacity = n;
	}
	void Pushback(int x)
	{

		//...扩容
		_a[_size++] = x;
	}
	int& Get(int pos)
	{
		assert(pos >= 0);
		assert(pos < _size);
		return _a[pos];
	}

};
int main()
{
	Stack st;
	st.Init();
	st.Pushback(1);
	st.Pushback(2);
	st.Pushback(3);
	st.Pushback(4);

	for (int i = 0; i < 4; i++)
	{
		cout << st.Get(i) << " ";
		/*cout << st[i] << " ";*/
	}
	cout << endl;

	for (int i = 0; i < 4; i++)
	{
		if (st.Get(i) % 2 == 0)
		{
			st.Get(i) *= 2; // 修改栈里面的值
		}
	}

	for (int i = 0; i < 4; i++)
	{
		cout << st.Get(i) << " ";
	}
	cout << endl;
	return 0;
}

在栈的基本实现里,如果我们要修改一个数或者得到一个数.我们正常是要写两个函数.但是用了引用做返回值后,我们可以只写一个函数来实现两个功能

野引用的出现

int& Add(int a, int b)
{
	int c = a + b;
	return c; //c出了Add这个函数就会销毁
}
int main()
{
	int& ret = Add(1, 2); //ret是已销毁空间里面c的别名
	cout << "Add(1, 2) is :" << ret << endl;
	return 0;
}

我们知道,局部变量c在栈区开辟,出了作用域Add就销毁.ret所接收的是一个已销毁空间的值.编译器在销毁的同时很有可能会清理空间.我们访问的是一片未知的区域.

举例:
我们入住酒店(调用函数,开辟空间),离开酒店(销毁空间),打扫酒店房间(清理空间).但是我们在离开时不小心把行李(变量)遗落在房间里面,我们的行李很有可能被清理走了.当我们再次进入房间(再次访问这个空间),我们会发现自己的行李不见了

image.png

  • 18
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海的宇宙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值