文章目录
============================ 【说明】 ===================================================
大家好,本专栏主要是跟学C++内容,自己学习了这位博主【 AI菌】的【C++21天养成计划】,讲的十分清晰,适合小白,希望给这位博主多点关注、收藏、点赞。
主要针对所学内容,通过自己的理解进行整理,希望大家积极交流、探讨,多给意见。后面也会给大家更新,其他一些知识。若有侵权,联系删除!共同维护网络知识权利!
=======================================================================================
1、什么是指针
学习C或C++,大家最为困惑的还是指针这个概念,想必大家一开始脑海中的指针可能像这样:
实际上,在C++中的指针相对更加抽象,学习时知道是指针,但又不知道怎么去用,作用如何?
简单来讲,指针其实就是一种特殊的变量,特殊在于这种变量所存的值不像之前那样又是整数、浮点数啥的,而是内存地址。我们可以利用一张图形象表示:
变量是要占内存空间的,图中Num
是一个变量,存放地址为0x8865(本案例虚构地址),存放的值为15,pNum
是一个指针,当然也是一个特殊变量,它存储的内容为0x8865,它自己也有存放地址0x8855
,再往下就会涉及二级指针、多级指针。。。
我们发现,指针和变量其实有相似之处,不同之处就是存放内容不一样。也可以发现,指针pNum
中的存储地址(存放内容)就是变量Num
的内存地址,因此,可以理解为,指针pNum
时指向内存单元Num
的特殊变量,说到这里,大致了解了什么是指针。
如果想更好利用指针,那么就要掌握最基本的四个部分:
(1) 如何声明指针
(2) 如何使用&
符号获取变量地址
(3) 如何使用指针存储地址
(4) 如何使用*
符号访问指针指向的数据
我们一一来解决上述四个问题。
1.1 如何声明指针
指针也是特殊变量,它和变量也是需要声明一下,例如声明一个整型变量是这样的:
int Num=10;
那么,声明指针时也是需要指明指针的类型,例如整型int,对应的是指针指向内存单元中存储的数的类型,例如:
int *pNum;
之前提到过,声明变量时最好养成赋予初值的习惯,同样声明指针时,也要给一个初值,例如:
int Num=0;
int *pNum=Null;
注:初始化为NULL的指针被称为NULL指针或空指针,空指针(即pAge) 是一个定 义在标准库中的值为零的常量。
1.2 如何使用&
符号获取变量地址
&
称为引用运算符,关于引用可以看【跟学C++】C++的String类用法详解【番外1】。Num表示变量,那么&Num则获取该变量的内存地址。例如:
#include<iostream>
using namespace std;
int main() {
int Num = 10;
cout << "变量Num的地址为:" << hex << &Num << endl;
return 0;
1.3 如何使用指针存储地址
前面了解了指针时用于存储内存地址的变量,也知道如何声明指针以及获取变量地址,我们可以利用指针来存储&
获取的地址。
根据上图,我们通过一个案例,来获取变量地址,并传递给指针。
#include<iostream>
using namespace std;
int main() {
int Num = 10;
cout << "变量Num的地址为:" << hex << &Num << endl;
int *pNum = &Num;
cout << "指针pNum中存放地址(存储内容)为:" << hex << pNum << endl;
return 0;
}
结果可以发现,Num
存放在内存中的地址和指针pNum
中存放的地址,说明&
可以获取Num
的内存地址,并传递给指针pNum
。
1.4 如何使用*
符号访问指针指向的数据
*
称为解除引用运算符,我们可以通过*pNum
来访问指针pNum
包含的地址所存储的值(其实*pNum
的值就是等于10,是值,而不是地址),例如:
#include<iostream>
using namespace std;
int main() {
int Num = 10;
cout << "变量Num的地址为:" << &Num << endl;
int *pNum = &Num;
cout << "指针pNum中存放地址(存储内容)为:" << pNum << endl;
cout << "Num的值为:" << Num << endl;
cout << "*pNum的值为:" << *pNum << endl;
return 0;
}
简单来说,指针pNum
是指向变量Num
对应的内存单元的,所以通过符号*就可以获得Num
对应的值。
2、动态分配内存
为了更好地管理程序占用的内存, C++提供了两个运算符: new
和delete
。 指针是包含内存地址的变量,在高效分配内存面扮演了重要的色。
2.1 动态分配内存和释放内存
使用new
来分配内存块,new
将返回指向一个指针,指向一个分配的内存。例如使用new
为整型int分配内存:
int *pNum=new int;
若为多个元素分配内存时:
int *pNum=new int[50];
注意:new
在分配内存时,并不是所有要求都能满足,要看系统状态以及内存资源的可用性。
我们分配内存后,如何使用完后,都要进行释放,例如:
1.单个元素
int *pNum=new int;
----程序----
delete pNum;
2.多个元素
int *pNum=new int[50];
----程序----
delete[] pNum;
注意:不使用分配的内存时,一定要释放,否则容易出现内存泄露,溢出现象。
使用案例,理解分配与释放内存:
#include<iostream>
using namespace std;
int main() {
//分配内存
int *pNum = new int;
cout << "请任意输入数字:";
cin >> *pNum;
cout << "输入的数字为:" << *pNum << endl;
cout << "数字存储地址为:" << pNum << endl;
//释放内存
delete pNum;
return 0;
}
2.2 带关键字const的指针
之前提到过关键const
的的含义,被关键字const
定义的变量,在程序中是不可修改的。指针是特殊的变量,所以const
关键字同样适用指针,对于const
的指针主要有三种:
(1) 指针指向的数据为常量(使用了const
关键字),不可修改,但是可以修改指针包含的地址(修改指针的值,或者理解为该指针不指向这个变量,去指向别的变量):
1.指针指向的数据为常量
int Num = 10;
const int *pNum = &Num; //不能更改pNum指向的数据Num的值,即变量Num值无法修改
2. 想将Num改为20,错误的做法
*pNum = 20; //错误
3. 正确的做法,修改指针指向,
int CopyNum = 20;
pNum = &CopyNum; //可改变指针指向的地址
(2) 指针包含的地址为常量(使用了const
关键字),可以修改指针指向数据的值,地址不可改:
int Num = 10;
int * const pNum = &Num; //不能更改pNum的值,即地址
*pNum=20;//可以修改
(3) 指针包含的地址和数据都为常量(使用了const
关键字),两者都不可修改。
int Num = 10;
const int * const pNum = &Num;
3、指针和数组
前面学过,声明一个数组:
int Array[10];
此时,编译器将分配一个固定长为10的内存空间,同时提供一个指向数组第一个元素的指针,其实Array
也是一个指针,指向数组第一个元素Array[0]
。
#include<iostream>
using namespace std;
int main()
{
int Array[10]={0,1,2,3,4,5,6,7,8,9};
int *pNum = Array;
cout<<"*pNum = "<<*pNum<<endl;
cout<<"Array[0] = "<<Array[0]<<endl;
return 0;
}
4、使用指针要注意的几个点
4.1 内存泄露
前面讲了,使用new
动态分配内存时,如果内存不在需要,就要用delete
进行释放,否则会减少其他程序使用的内存空间,降低运行速度,也容易发生内存泄露。
4.2 无效指针
我们知道,利用*
可以访问指针所指向变量的值,我们务必要保证指针指向的是有效内存但愿,否则容易使程序崩溃,就是无效指针。无效指向的原因有很多,比如之前所讲没有对指针进行初始化、使用new
分配内存空间值过大等等。
5、总结
以上是C++中,指针的一些基本知识,在这个基础上,可以再深入理解指针其他相关知识,例如多级指针等,大家可以把更多知识分享到评论区。
最后,长话短说,大家看完就好好动手实践一下,切记不能三分钟热度、三天打鱼,两天晒网。大家也可以自己尝试写写博客,来记录大家平时学习的进度,可以和网上众多学者一起交流、探讨,我也会及时更新,来督促自己学习进度。一开始提及的博主【AI菌】,个人已关注,并订阅了相关专栏(对我有帮助的),希望大家觉得不错的可以点赞、关注、收藏