c++:引用是什么?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;
}

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

引用的使用规范

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

引用必须初始化

一个变量可以有多个别名

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

arduino 复制代码
#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;
}

引用不能改变指向

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

c 复制代码
#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;
}

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

引用的使用场景

引用做参数

ini 复制代码
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;
}

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

引用做返回值

ini 复制代码
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;
}

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

野引用的出现

c 复制代码
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所接收的是一个已销毁空间的值.编译器在销毁的同时很有可能会清理空间.我们访问的是一片未知的区域.

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

相关推荐
AMoon丶几秒前
Golang--多种控制结构详解
java·linux·c语言·开发语言·后端·青少年编程·golang
IT_陈寒11 分钟前
SpringBoot开发效率提升50%的5个隐藏技巧,官方文档都没告诉你!
前端·人工智能·后端
liuyao_xianhui13 分钟前
递归_反转链表_C++
java·开发语言·数据结构·c++·算法·链表·动态规划
CoderCodingNo13 分钟前
【GESP】C++七级考试大纲知识点梳理 (3) 图论基础与遍历算法
c++·算法·图论
勇闯逆流河16 分钟前
【Linux】Linux基础开发工具(git、dbg)
linux·运维·服务器·开发语言·c++·git
猹叉叉(学习版)18 分钟前
【ASP.NET CORE】 10. 数据校验
笔记·后端·c#·asp.net·.netcore
DJ斯特拉21 分钟前
SpringBoot项目的基本构建
java·spring boot·后端
小小心愿家23 分钟前
初识 maven,Spring boot,Spring MVC
java·后端·spring
Victor35627 分钟前
MongoDB(41)如何使用$group阶段?
后端
Victor35628 分钟前
MongoDB(40)如何使用$match阶段?
后端