一、指针的本质与内存模型
指针是C/C++的核心特性,本质是内存地址的变量化表示。每个变量在内存中占据连续的字节空间,地址是内存单元的唯一编号(如0x0028FF40
)。指针变量存储的是目标数据的首地址,通过地址间接操作数据。
内存模型示例:
int num = 97; // 假设分配在地址0x0028FF40
int* p = # // p存储0x0028FF40,*p解引用得到97
- 步长:指针类型决定地址增减的步长(如
int*
步长为4字节,char*
为1字节)。
二、指针的声明与操作
-
声明与初始化
int* p; // 声明int型指针 int a = 10; p = &a; // p指向a的地址 int* q = NULL; // 空指针,避免野指针问题
-
核心操作符
&
:取地址符,获取变量内存地址(如&a
)。*
:解引用符,访问指针指向的值(如*p = 20
修改a的值)。
-
指针运算
- 算术运算:
p++
使指针移动到下一个元素地址(步长由类型决定)。 - 关系运算:比较指针地址大小(需指向同一数组)。
- 算术运算:
三、多级指针与复杂类型
-
二级指针
指向指针的指针,用于动态内存管理和函数参数传递:int pp = &p; // pp存储p的地址 pp = 30; // 修改a的值为30
-
指针与数组
- 数组名是首元素地址的常量指针(如
int arr; int* p = arr;
)。 - 指针数组 vs. 数组指针:
int* arr; // 数组元素为int指针 int (*pArr); // 指向含5个int元素的数组的指针
- 数组名是首元素地址的常量指针(如
-
函数指针
指向函数的指针,用于回调机制:void (*funcPtr)(int) = &myFunction; // 声明并赋值 funcPtr(10); // 调用函数
-
函数指针
- 本质是函数
- 就是返回是指针的函数,即返回值是指针,是一个地址
- 作用代码简洁、一定程度上节约内存
//三种写法都可以
int *fun(int x,int y);
int * fun(int x,int y);
int* fun(int x,int y);
四、指针与动态内存管理
-
动态分配
- C:
malloc/calloc
分配堆内存,需手动释放(free
)。 - C++:
new/delete
支持类型安全:int* arr = new int; // 动态数组 delete[] arr; // 释放内存
- C:
-
智能指针(C++)
unique_ptr
:独占所有权,禁止拷贝。shared_ptr
:引用计数,自动释放内存。
五、高级应用与注意事项
-
常量指针 vs. 指针常量
const int* p1; // 指向常量的指针(值不可改) int* const p2; // 指针常量(地址不可改)
-
内存安全
- 野指针:未初始化或已释放的指针(需置为
NULL
)。 - 内存泄漏:忘记释放动态内存(推荐使用RAII机制)。
- 野指针:未初始化或已释放的指针(需置为
-
与引用的区别
引用是别名(编译期优化),指针是实体变量,支持运算和多级间接访问。
六、典型应用场景
- 数据结构:链表、树的节点链接。
- 函数参数:传递大型结构体避免拷贝。
- 系统编程:直接操作硬件寄存器或内存映射。
总结
指针是C/C++高效性和灵活性的核心,但也带来内存管理的复杂性。理解其底层机制(地址、步长、类型)和现代实践(智能指针、RAII)是掌握关键。建议结合调试工具(如Valgrind)验证内存操作安全性。
demo
#include <iostream>
using namespace std;
// 定义结构体用于示例
struct Student {
int age;
string name;
};
int main() {
// 1. 基础变量指针
int a = 10;
int* p1 = &a;
*p1 = 20;
cout << "基础指针: " << a << endl; // 输出 20 [7]()
// 2. 空指针与野指针
int* p2 = nullptr; // 安全空指针
// int* p3; // 未初始化野指针(注释避免运行时崩溃)
// 3. 数组指针操作
int arr[] = {1,2,3,4,5};
int* p4 = arr;
cout << "数组指针: " << *(p4 + 2) << endl; // 输出 3 [3]()
// 4. 字符串指针
const char* str = "Hello";
cout << "字符串指针: " << str[1] << endl; // 输出 'e' [6]()
// 5. 结构体指针
Student s = {20, "Tom"};
Student* p5 = &s;
cout << "结构体指针: " << p5->name << endl; // 输出 Tom [5]()
// 6. 动态内存分配
int* p6 = new int(100);
cout << "动态内存: " << *p6 << endl;
delete p6; // 必须释放 [7]()
// 7. 多维数组指针
int matrix[2][3] = {{1,2,3}, {4,5,6}};
int (*p7)[3] = matrix;
cout << "多维数组: " << p7[1][2] << endl; // 输出 6 [3]()
// 8. 函数指针
int (*funcPtr)(int, int) = [](int x, int y) { return x + y; };
cout << "函数指针: " << funcPtr(3,5) << endl; // 输出 8 [6]()
return 0;
}