跳到主要内容
C++ 指针基础与内存管理总结 | 极客日志
C++ 算法
C++ 指针基础与内存管理总结 综述由AI生成 总结了 C++ 指针的核心概念与应用。内容包括指针的基础声明与赋值、野指针与空指针的安全处理、指针运算规则及数组操作。重点讲解了动态内存分配(new/delete)与静态管理的区别,以及数组元素的增删实现逻辑。此外,还涵盖了指针悬挂问题的成因与预防,并详细区分了常量指针、指向常量的指针及指向常量的常量指针三种类型及其使用场景。通过代码案例展示了内存地址操纵的具体实践。
孤勇者 发布于 2026/3/26 更新于 2026/5/12 17 浏览1 指针基础
在 C++ 中,指针是至关重要的组成部分。它是 C++ 语言最强大的功能之一,也是最棘手的功能之一。
指针具有强大的能力,其本质是协助程序员完成内存的直接操纵
1.1 指针的声明和赋值
声明:变量类型 * 指针变量名;
赋值:指针变量名 = 内存地址值;
int p;: 声明整型变量,变量为 p
int num =10 int * p;: 声明 p 为指针变量,p 存放的为内存地址****为什么为 int?指针 p 存放 num 变量的地址,num 本身为 int 变量。
变量类型 (如上 int) 表示,指针 (内存地址) 指向的内存区域,存放的是整型数据
p=#:&:获取 num 的内存地址,提供给 p
cout << p;输出 num 变量地址
cout << *p;输出 10
1.2 指针解释
1.3 案例
#include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
num = ;
*p;
cout << << p << endl;
cout << << &num << endl;
cout << << *p << endl;
*p = ;
cout << << *p << endl;
cout << << num << endl;
}
;
}
int
10
int
"指针变量 p 中记录的地址是:"
"&num 取地址为:"
"取指针变量记录地址中存放的数值为:"
20
"*p 赋值后结果为:"
"num 结果为:"
return
0
指针变量 p 中记录的地址是:0 x16443ffc04
& num 取地址为:0 x16443ffc04
取指针变量记录地址中存放的数值为:10
*p 赋值后结果为:20
num 结果为:20
2 野指针和空指针 野指针:被声明但未初始化 (赋值) 的指针。这个指针会指向随机的内存空间,可能导致未知问题。
普通变量是对数值进行操作,不会有安全问题,所以没有'野变量'一说。
指针对内存直接操作,所以一旦声明但未赋值,就是'野指针',一旦使用,后果不可预料。
为避免野指针,应养成良好的编程习惯,及时初始化,或将指针置为空指针更为安全。
2.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *p;
cout << p << endl;
cout << "hello" << endl;
}
return 0 ;
}
2.2 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *p = NULL ;
int *p1 = nullptr ;
*p = 10 ;
*p1 = 10 ;
cout << "hello" << endl;
}
return 0 ;
}
2.3 总结 声明会立刻分配内存,分配的内存不一定是干净的 (比如其它程序残留)。
使用普通变量影响不大,但是指针不一样,会导致安全问题。
1.野指针:仅声明未赋值的指针。不可应用,因为其指向的内存区域是随机的、未知的。
2.空指针:将指针赋值为'空':NULL、nullptr,避免指向具体内存,更加安全。
3.空指针也不是正常的指针,只是过渡,指针最终要给与具体值,否则就不要用指针。
3 指针运算 尽管指针变量内记录的是内存地址,但仍可以进行基础的数学计算。
指针运算是对指针的基础型操作,非常适合操纵数组并配合做动态内存分配。
3.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int num = 10 ;
int *p =#
cout << "指针变量 p 记录的地址是:" << p << endl;
p++;
cout << "指针变量 p 进行加 1 操作,记录的地址是:" << p << endl;
double num1 = 10 ;
double *p1 =&num1;
cout << "指针变量 p1 记录的地址是:" << p1 << endl;
p1++;
cout << "指针变量 p1 进行加 1 操作,记录的地址是:" << p1 << endl;
p1 += 4 ;
cout << "指针变量 p1 进行加 4 操作,记录的地址是:" << p1 << endl;
int v[]={1 ,2 ,3 ,4 ,5 };
int *vp = v;
cout << "数组的第一个元素是:" << *vp << endl;
cout << "数组的第一个元素是:" << v[0 ]<< endl;
cout << "数组的第 2 个元素是:" << *(vp +1 )<< endl;
cout << "数组的第 2 个元素是:" << v[1 ]<< endl;
*(vp +2 )=33 ;
cout << "数组的第 3 个元素是:" << *(vp +2 )<< endl;
cout << "数组的第 3 个元素是:" << v[2 ]<< endl;
int v2[]={1 ,2 ,3 ,4 ,5 ,6 ,7 };
int *p2 = v2;
for (int i =0 ; i <sizeof (v2)/sizeof (v2[0 ]); i++){
cout <<*(p2 + i);
}
}
return 0 ;
}
指针变量 p 记录的地址是:0 x2b4d7ff6f4
指针变量 p 进行加 1 操作,记录的地址是:0 x2b4d7ff6f8
指针变量 p1 记录的地址是:0 x2b4d7ff6e8
指针变量 p1 进行加 1 操作,记录的地址是:0 x2b4d7ff6f0
指针变量 p1 进行加 4 操作,记录的地址是:0 x2b4d7ff710
数组的第一个元素是:1
数组的第一个元素是:1
数组的第 2 个元素是:2
数组的第 2 个元素是:2
数组的第 3 个元素是:33
数组的第 3 个元素是:33
1234567
3.2 练习 有数组:int v1[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for 循环遍历数组,使用指针取出每一个元素并打印输出。
#include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int v2[]={1 ,2 ,3 ,4 ,5 ,6 ,7 };
int *p2 = v2;
for (int i =0 ; i <sizeof (v2)/sizeof (v2[0 ]); i++){
cout <<*(p2 + i)<< endl;
}
}
return 0 ;
}
4 内存动态分配 动态内存分配:即由程序员手动的进行内存空间的分配、内存空间的释放等内存管理操作。
C++ 代码中,变量、数组等对象的创建,是由 C++ 自动分配内存的为,称之为 (自动) 静态内存分配。
(自动) 静态内存管理,是不会进行内存空间的自动清理的。(无垃圾回收机制)
我们需要手动的管理内存,即手动分配,用完清理 。
4.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *p =newint;
*p = 10 ;
cout << "new 申请的 4 字节空间内,存放的是:" << *p << endl;
delete p;
int *p_arr =newint[5 ];
p_arr[0 ]=10 ;
p_arr[1 ]=20 ;
p_arr[2 ]=30 ;
p_arr[3 ]=40 ;
p_arr[4 ]=50 ;
cout << "数组的第 1 个元素是:" << p_arr[0 ]<< endl;
cout << "数组的第 2 个元素是:" << p_arr[1 ]<< endl;
cout << "数组的第 3 个元素是:" << p_arr[2 ]<< endl;
cout << "数组的第 4 个元素是:" << p_arr[3 ]<< endl;
cout << "数组的第 5 个元素是:" << p_arr[4 ]<< endl;
*(p_arr)=0 ;
*(p_arr +1 )=1 ;
*(p_arr +2 )=2 ;
*(p_arr +3 )=3 ;
*(p_arr +4 )=4 ;
cout << "数组的第 1 个元素是:" << *(p_arr)<< endl;
cout << "数组的第 2 个元素是:" << *(p_arr +1 )<< endl;
cout << "数组的第 3 个元素是:" << *(p_arr +2 )<< endl;
cout << "数组的第 4 个元素是:" << *(p_arr +3 )<< endl;
cout << "数组的第 5 个元素是:" << *(p_arr +4 )<< endl;
delete [] p_arr;
}
return 0 ;
}
5 静态内存管理和手动管理方式区别 传统方式创建普通变量或数组,其内存由 C++ 自动管理,称之为:
静态内存管理
静态内存管理:不会清理用不到的内存空间
动态内存管理:程序员手动管理内存空间
new 运算符申请空间,提供该空间的指针 (地址)
delete 运算符申请的空间,仅用于 new 申请的空间
建议:写完 new 后,立刻写 delete,然后再写业务逻辑代码 。
优势:
手动控制内存,避免内存空间浪费
劣势:
考验程序员水平,用的好效率高,用不好有反效果
5.1 练习 数组的内存控制
1.通过 new 运算符,申请 10 个 int 元素的数组内存空间并完成赋值。
2.通过 for 循环,基于指针形式取出数组元素并打印输出。
3.通过 delete 运算符,清理申请的内存空间。
#include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *p_arr1 =newint[10 ];
for (int i =0 ; i <10 ; i++){
*(p_arr1 + i)= i +1 ;
}
for (int i =0 ; i <10 ;++i){
cout <<*(p_arr1 + i)<< endl;
}
delete [] p_arr1;
}
return 0 ;
}
6 数组元素的移除 C++ 内置并未提供对数组元素进行增加 (插入)、移除的功能,需要手动实现 (vector 容器提供,后续学习)。
6.1 思路
6.2 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *pArr =newint[5 ]{1 ,2 ,3 ,4 ,5 };
int *pNewArr =newint[4 ];
for (int i =0 ; i <5 ; i++){
if (i ==2 ){continue ;}
if (i >2 ){ pNewArr[i -1 ]= pArr[i];}
else { pNewArr[i]= pArr[i];}
}
delete [] pArr;
pArr = pNewArr;
for (int i =0 ; i <4 ; i++){
cout << "新数组的元素是:" << pNewArr[i]<< endl;
}
}
return 0 ;
}
新数组的元素是:1
新数组的元素是:2
新数组的元素是:4
新数组的元素是:5
7 数组元素的插入
7.1 思路
7.2 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int *pArr =newint[5 ]{1 ,2 ,3 ,4 ,5 };
int *pNewArr =newint[7 ];
int offset =0 ;
for (int i =0 ; i <7 ; i++){
if (i ==1 ){ pNewArr[i]=11 ; offset++;continue ;}
elseif (i ==3 ){ pNewArr[i]=66 ; offset++;continue ;}
pNewArr[i]= pArr[i - offset];
}
delete [] pArr;
pArr = pNewArr;
}
return 0 ;
}
8 指针悬挂 指针指向区域已经被回收 (delete),这种问题称之为:指针悬挂。 。
所以,总结出两点经验:
1.不要轻易进行指针之间相互赋值
2.delete 回收空间前,确保此空间 100% 不再被使用
9 常量指针
9.1 指向 const 的指针 指向 const 的指针:表示指向区域的数据,是不变的,但可以更换指向。
9.1.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int num1 = 10 ;
int num2 = 100 ;
constint*p =&num1;
cout << "指针 p 当前指向的数据是:" << *p << endl;
p =&num2;
cout << "指针 p 当前指向的数据是:" << *p << endl;
}
return 0 ;
}
9.2 const 指针 const 指针:表示指针本身不可更改,但指向的数据可以更改。
9.2.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int num1 = 10 ;
int num2 = 100 ;
int *const p =&num1;
cout << "指针 p 当前指向的数据是:" << *p << endl;
*p=20 ;
cout << "指针 p 当前指向的数据是:" << *p << endl;
}
return 0 ;
}
9.3 指向 const 的 const 指针 指向 const 的 const 指针:指针和指向区域的值,都不可更改。
9.3.1 案例 #include <iostream>
using namespace std;
int main () {
system ("chcp 65001" );
{
int num1 = 10 ;
int num2 = 100 ;
constint*const p =&num1;
cout << "指针 p 当前指向的数据是:" << *p << endl;
}
return 0 ;
}
9.4 总结 相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online