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

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

相关推荐
齐 飞1 分钟前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
lulu_gh_yu15 分钟前
数据结构之排序补充
c语言·开发语言·数据结构·c++·学习·算法·排序算法
LunarCod18 分钟前
WorkFlow源码剖析——Communicator之TCPServer(中)
后端·workflow·c/c++·网络框架·源码剖析·高性能高并发
ULTRA??1 小时前
C加加中的结构化绑定(解包,折叠展开)
开发语言·c++
码农派大星。1 小时前
Spring Boot 配置文件
java·spring boot·后端
凌云行者1 小时前
OpenGL入门005——使用Shader类管理着色器
c++·cmake·opengl
凌云行者1 小时前
OpenGL入门006——着色器在纹理混合中的应用
c++·cmake·opengl
杜杜的man1 小时前
【go从零单排】go中的结构体struct和method
开发语言·后端·golang
幼儿园老大*1 小时前
走进 Go 语言基础语法
开发语言·后端·学习·golang·go
llllinuuu2 小时前
Go语言结构体、方法与接口
开发语言·后端·golang