指针总结
一、什么是指针?
想必大家在初学指针的时候,都会感觉指针很神奇,但是对指针又不是很了解,而且指针的内容很多,很杂。于是,在学完指针后,我进行了总结。
(1)那什么是指针呢?
指针其实就相当于是地址,指针分为常量指针和变量指针.
指针变量:其他的变量类似,可以随时改变其中的值。只不过这个变量存储的是地址。
谈到地址,我们平常写的数据,变量,在计算机中都是以字节为单位进行存储的,一个字节对应一个地址。
所以指针就是保存这些变量的地址,然后通过地址来访问数据。
常量指针(在下一篇总结有详细讲到,所以这里的指针都是指的是变量,简说为指针)
这里int a占4个字节,如果用指针 int *p=&a;p存储的是a的首地址。
(2)了解几个术语
1.定义:声明一个变量,但不赋初值
2.初始化:对声明的变量赋值
3.指向:如果指针保存的整形变量的地址,我们就说指针指向这个整形变量
4.解引:得到指针指向地址的值.
int a=10;
int *pr=&a;
cout<<*pr<<endl;//*pr相当于10
这里*pr就是取的pr中的值,注意:int *pr中的 pr和 后面的pr 不同,前者是定义一个指针,后者是得到a的值
(3)指针如何定义呢?
指针定义和其他变量定义类似。
定义并初始化变量(定义:int a; 初始化: a =10)
int a =10;
double b=10.0;
定义并初始化指针变量
int *P1=NULL;//定义一个指向整形的指针(指针p保存的是整形变量的地址)
double *p2=NULL;//指向双精度的指针
*的位置没有要求,可以int* p1,int *p1,int*p1,但为了美观,个人推荐int *p1这种形式。注意如果我门声明int* p1,p2;
p1是指针,而p2是int类型的变量。我门应该写成int *p1,*p2;
这里指针等于NULL(0),是给指针进行初始化,后面会详细讲解
二、为什么要使用指针?
有人会问,我们可以直接访问变量呀,为啥还要么先定义指针来获得地址,再通过地址访问变量,这样不是很多余吗?
确实如此,但是指针自然有它的妙处
(1).函数的值传递,无法通过形参来改变实参的值
比如我们交换两个数
void swap(int a ,int b){
int temp=a;
a=b;
b=temp;
int main(){
int x=1;
int y=0;
swap(x,y);
cout<<x<<" "<<y;
}
会发现在main函数中x和y的值并没有改变
原因:其实是在声明形参a和b时,只是把x和y值的拷贝给了a和b。栈为a和b重新分配了内存空间,交换的只是a和b的值
(这里不懂什么是栈空间的可以看我之前写的c++、c内存分配
[c++内存分布](https://blog.csdn.net/weixin_46273997/article/details/105268061)
那怎样解决呢?
我们可以用指针或引用
指针版:
void swap(int *a ,int *b){
int temp=*a;
*a=*b;
*b=temp;
int main(){
int a=1;
int b=0;
swap(&a,&b);
cout<<a<<" "<<b;
`会发现这里a和b的值就交换了,因为我们传入的是a和b的地址,即指针指向a和b的内存地址,这样通过指针,就能交换。
引用版:
void swap(int &a ,int &b){
int temp=a;
a=b;
b=temp;
int main(){
int a=1;
int b=0;
swap(a,b);
cout<<a<<" "<<b;
(引用后面会讲到)
(2).有多个返回值
函数的返回值只能有一个,但使用指针可以有多个返回值,所谓多个返回值并不是
int swap(int a,int b){
int temp=a;
a=b;
b=temp;
return a,b;
}
而是指的是,我么传入多个地址到函数中,对传入的地址进行操作,就相当于返回多个返回值,比如
bool add_blood(int *blood){
if((*blood)>=1000){
*blood+=1000;
}
return true;
}
int main(){
int blood=1000;
if(add_blood(&blood)){
cout<<"加血成功"<<endl;
}
else{
cout<<"加血失败"<<endl;
}
}
这里我们返回了true的同时,又改变了blood 的值;
(3).减少值传递带来的额外开销,提高代码效率
比如我们在用形参接收实参时,尽可能使用指针会减少内存的使用。
这里补充一个小知识:即指针的所占的内存是固定不变的,不管是什么类型的指针,所占的字节数不变,具体是多少有系统决定,一般32位系统占4个字节,64位系统占8个字节
所以我们用指针作形参能节省空间,比如形参接收一个结构体,那么会在栈空间上开辟一个相同大小的内存来存储,但是如果我们使用结构体指针,这样就会节省内存空间
#include <iostream>
#include <string>
using namespace std;
struct student{
int age;
char sex;
string name;
};
void change(struct student b){
b.age=19;
b.sex='m';
b.name="如花";
}
void change(struct student *b){
b->age=19;
b->sex='m';
b->name="如花";
}
int main(){
struct student a;
a.age=18;
a.sex='f';
a.name="秋香";
change(a):
change(&a);
return 0;
}
这里a占多少字节可用
sizeof(a)计算,change(a),就相当于main函数中中有一个结构体,然后change函数中又有一个结构体,这样不是浪费了内存空间? 相反如果我们使用指针,效率就更高了
三、指针的分类
野指针,函数指针,数组指针,指针数组,指向常量的指针,指针常量,数组的指针,结构体指针,特殊的指针--引用将在下一篇文章中进行介绍
这里先简单介绍一下野指针
所谓野指针就是你定义了一个指针,但并没有为它初始化,这类指针就叫野指针.如果不初始化,里面存储的地址是随机的,不清楚是什么,如果后面使用了这个没初始化的指针,可能会造成的后果,所以大家记住申明指针时一定要初始化哟!
下一篇文章会介绍其他类型的指针
传送门
最后附上一个学院的b站二维码,里面很多视频是免费的,有很多大佬为你解答疑惑,还有很多活动,大家可以在这里进行交流