理解C++中*,&的作用

在开始说前, 先给大家导入一个思想, 其实所有的程序, 在运行之前, 系统都要把程序的代码和数据导入到内存之中.

不知道大家有没有开过外挂,外挂的原理就是去修改内存.


举个例子:

你在玩一个游戏,你的角色的攻击力是1(因为你没充钱), 你想把它改成10000, 但是你又不想充钱,那你要怎么做呢?

答: 假如这个游戏中攻击力对应的变量是x, 那你就要找到x的内存地址, 把这个地址中的值改为10000, 那你就会发现, 你的攻击力变成了10000了!

x

进入正题!!!


重要的几点

  • 每个变量都有对应的内存地址和对应的值 (不理解没关系, 下面有图)
  • 变量声明的时候都会开辟新的内存地址 (引用的时候不会开辟新的内存地址, 引用不清楚没关系,下文的鲁迅会教你的!)
  • 接下来的代码, 我都会把输出内容写在main函数最后的注释中.

&符号

先来看一段简单代码

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
}

我们定义了一个变量a,把5赋值给了a, 那么现在内存中是怎么样的呢?

x


现在的内存是这样的, 那我们现在怎么去取出a所对应的内存地址呢?

答: 在a变量前加取址符号"&"

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	cout<<&a<<endl;
	
	// 输出
	// 0x71fe4c
}

那现在我们可以得出,a在内存中就是

在这里插入图片描述


你可能会问:"0x71fe4c"是什么意思呢?

答: "0x71fe4c"表示一个16进制数,在这里,它是a的内存地址

OK~接下来来看这个代码!

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int &b = a;
}

纳尼? 变量声明 + 取地址符号, 晕了晕了...

其实, 这个时候"&"符号的作用不再是"取地址"了, 它现在的作用是"引用".

怎么理解"引用"呢? 我们接下来来看个图

图片

其实咧, 鲁迅和周树人指的都是一个人!!! 那我们可以说, 鲁迅是周树人的引用, 或者周树人是鲁迅的引用, 2个名称指的都是同一个人!!! 所以抓捕周树人就是抓鲁迅呀.

现在我们看看上面的代码

int &b = a, 这表示我们声明一个引用变量b, b是a的别名.(这个时候不会为b开辟新的内存地址)

那么这个时候, a,b的内存地址和值都是一样的.

不信? 我们输出一下他们的地址和值.

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int &b = a;
	cout<<"a,b的地址:"<<&a<<" "<<&b<<endl;	// 在这里&是取指符号 
	cout<<"a,b的值:"<<a<<" "<<b<<endl;
	
	// 输出
	// a,b的地址:0x71fe34 0x71fe34
	// a,b的值:5 5 
}

现在内存如下:

在这里插入图片描述

这时候, 假如我们修改了b的值, 那a的值会变吗?

答: 会! 看下面代码.

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int &b = a;
	b = 100;
	cout<<"a,b的地址:"<<&a<<" "<<&b<<endl;	// 在这里&是取指符号 
	cout<<"a,b的值:"<<a<<" "<<b<<endl;
	
	// 输出
	// a,b的地址:0x71fe34 0x71fe34
	// a,b的值:100 100 
}

可以看出, 修改了b的值,a和b的值都变了. (本质上就是修改内存中的值嘛)


接下来我们来总结一下 "&"这个符号

1. 在变量声明的时候, "&"表示该变量是一个引用类型的变量.(必须有另外一个变量赋值给该变量,否则不给编译!)

2. 不在变量声明的时, "&"表示取出该变量的内存地址


*符号

我们现在已经可以取出a的地址了, 那我们是否可以存储这个地址呢?

答: 可以! 我们可以声明一个指针变量来存储a的地址, 把a的地址赋值给它

你可能又会问, 什么是指针变量呢?

答: 指针变量就是指: 该变量的值是一个地址.


接下来上代码

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int *p;
	p = &a; 
	cout<<p<<endl;
	// 输出
	// 0x71fe44
}

int *p 表示声明一个变量p, p是一个int类型的指针.


首先, 你可能会问: p是一个int类型的指针是什么意思呢?

答: 它表示p的值是一个地址,而且这个地址对应的值是一个int类型的. (不理解没关系,下面有图可以让你理清关系).

而p = &a, 表示把a的地址赋值给p, 那现在p的值就是a的地址.


如果此时我们要取p的值(内存地址)对应的值, 我们应该怎么做呢? (不理解没关系,下面有图)

答: 用"*p" (注意现在这个*和int *p这的*功能不一样喔)

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int *p;
	p = &a; 
	cout<<*p<<endl;
	// 输出
	// 5
}

问: 怎么得到p对应的内存地址呢?

答: 用上面所学的"&", "&p"就可以取出变量p的内存地址.

#include<bits/stdc++.h>
using namespace std;

int main(){
	int a = 5;
	int *p;
	cout<<&p<<endl;
	// 输出 
	// 0x71fe40
}

OK,接下来我画个图, 看看a和p在内存中是怎么样的

在这里插入图片描述

这应该很直观了吧~ (为了把a和p的关系看得更清楚, 我自己画了个箭头)


接下来我们来总结一下 *这个符号

1. 在变量声明的时候, *表示该变量是一个指针变量.

2. 不在变量声明时, *表示取出内存地址中的值 (通常是把内存地址赋值给一个指针类型的变量, 然后通过" *变量名 "来取出内存地址的值)


综合实例(交换2个变量的值)

我们来看这一段代码, 看看它究竟能不能交换2个数的值

#include<bits/stdc++.h>
using namespace std;


void swap(int x,int y){
	int t = x;
	x = y;
	y = t;
} 

int main(){
	int a,b;
	a = 1;
	b = 2;
	cout<<"交换前的值 a,b : "<<a<<","<<b<<endl; 
	swap(a,b);
	cout<<"交换后的值 a,b : "<<a<<","<<b<<endl; 
	
	// 输出
	// 1 2
	// 1 2
	
}

答案是不能!!! 为什么呢?

答: 因为在调用函数swap(a,b)的时候, 进入swap函数时, x,y会开辟新的内存地址. 不信我们输出一下a,b,x,y的内存地址.

#include<bits/stdc++.h>
using namespace std;


void swap(int x,int y){
	int t = x;
	x = y;
	y = t;
	cout<<"x的地址: "<<&x<<endl;
	cout<<"y的地址: "<<&y<<endl;
} 

int main(){
	int a,b;
	a = 1;
	b = 2;
	cout<<"a的地址: "<<&a<<endl;
	cout<<"b的地址: "<<&b<<endl;
	swap(a,b);
	// 输出 
	// a的地址: 0x71fe4c
	// b的地址: 0x71fe48
	// x的地址: 0x71fe20
	// y的地址: 0x71fe28 
}

可以看出,a的内存地址不等于x的内存地址, b的内存地址也不等于y的内存地址.


那如果要让a和x的内存地址一样,b和y的内存地址一样,我们要怎么做呢?以及为什么我们要这样做呢?

答: 我们可以用上面教的"&"符号来表示引用. 这样我们就可以通过操作x,y变量来改变a,b变量的值 (因为x,y和a,b的内存地址是一样的).

#include<bits/stdc++.h>
using namespace std;

// 之前是swap(int x,int y) 
void swap(int &x,int &y){
	int t = x;
	x = y;
	y = t;
	cout<<"x的地址: "<<&x<<endl;
	cout<<"y的地址: "<<&y<<endl;
} 

int main(){
	int a,b;
	a = 1;
	b = 2;
	cout<<"a的地址: "<<&a<<endl;
	cout<<"b的地址: "<<&b<<endl;
	cout<<"交换前的值 a,b : "<<a<<","<<b<<endl; 
	swap(a,b);
	cout<<"交换后的值 a,b : "<<a<<","<<b<<endl; 
	// 输出 
	// a的地址: 0x71fe3c
	// b的地址: 0x71fe38
	//交换前的值 a,b : 1,2
	// x的地址: 0x71fe3c
	// y的地址: 0x71fe38 
	// 交换后的值 a,b : 2,1 
}

可以看出, 这个时候a和x的内存地址是一样的, x和y的内存地址是一样的.而且我们也交换成功了!


假如我们现在不用引用, 我们是否有另外的方法交换2个变量的值呢?

答: 肯定可以呀. 我们接下来用指针的方式.

#include<bits/stdc++.h>
using namespace std;

// 之前是swap(int x,int y) 
// 		swap(int &x,int &y) 
void swap(int *x,int *y){
	int t = *x;
	*x = *y;
	*y = t;
} 

int main(){
	int a,b;
	a = 1;
	b = 2;
	cout<<"交换前的值 a,b : "<<a<<","<<b<<endl; 
	swap(&a,&b);
	cout<<"交换后的值 a,b : "<<a<<","<<b<<endl; 
	
	// 输出 
	// 交换前的值 a,b : 1,2 
	// 交换后的值 a,b : 2,1 
}


可以看出交换成功了, 为什么呢?

答: 因为我们把a的地址传递给了x, b的地址传递给了y, 然后再对这2个内存地址进行操作, 我又来画图了! (截屏不够大,我只能把这个图片分为2次发哈~)

在这里插入图片描述在这里插入图片描述

很直观吧!!!


OK,接下来我们来看这一段代码.

#include<bits/stdc++.h>
using namespace std;


int main(){
	int a = 10;
	int* p1 = &a;
	int* &p2 = p1;
}

这里面 int* &p2 是什么东西啊?

我们运用一下总结的 * 和 & 的作用.

int* &p2 中的 * 和 & 都用在变量声明, 所以 int* 表示p2是一个指向int类型的指针, 而&p2, 表示p2是一个引用.

那现在我再画个图,你们就知道啦~

在这里插入图片描述

如何证明呢? 我们来输出他们的值和地址.

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int a = 10;
	int* p1 = &a;
	int* &p2 = p1;
	
	cout<<"a的地址: " <<&a<<"  "<<"a的值:"<<a<<endl;
	cout<<"p1的地址: " <<&p1<<"  "<<"p1的值:"<<p1<<endl;
	cout<<"p2的地址: " <<&p2<<"  "<<"p2的值:"<<p2<<endl;
	
	// 输出
	// a的地址: 0x71fe34  a的值:10
	// p1的地址: 0x71fe28  p1的值:0x71fe34
	// p2的地址: 0x71fe28  p2的值:0x71fe34 
}

搞定!!!


最后

如果有不正确的地方, 欢迎各位指出哈,如果你们觉得有收获, 就给我点个赞哈~

  • 58
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值