1. 指针的本质与基础概念
指针是C++中最强大也最令人困惑的特性之一。理解指针的本质是掌握C++内存管理的关键。指针本质上是一个变量,但这个变量存储的不是普通的数据值,而是另一个变量的内存地址。
1.1 指针的基本语法
在C++中声明指针的基本语法是:
cpp复制type *pointer_name;
这里的type可以是任何有效的C++数据类型,pointer_name是指针变量的名称。星号*在这里表示这是一个指针变量。
举个例子:
cpp复制int *ip; // 整型指针
double *dp; // 双精度浮点型指针
char *cp; // 字符型指针
1.2 指针的初始化与使用
指针在使用前应该被初始化,否则它可能指向一个随机的内存地址,这会导致程序崩溃或不可预测的行为。指针可以通过取地址运算符&来获取变量的地址:
cpp复制int var = 42;
int *ptr = &var; // ptr现在存储了var的地址
要访问指针指向的值,我们使用解引用运算符*:
cpp复制cout << *ptr; // 输出42
1.3 指针的大小与类型
在32位系统中,指针通常是4字节大小;在64位系统中,指针通常是8字节大小。无论指针指向什么类型的数据,指针本身的大小都是相同的。
cpp复制cout << sizeof(int*); // 输出4或8
cout << sizeof(double*); // 输出4或8
cout << sizeof(char*); // 输出4或8
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 指针的运算与数组关系
指针和数组在C++中有着密切的关系。实际上,数组名在很多情况下会被转换为指向数组第一个元素的指针。
2.1 指针算术运算
指针支持四种基本的算术运算:++、--、+、-。这些运算不是普通的数值运算,而是基于指针所指向类型的大小进行的。
cpp复制int arr[5] = {10, 20, 30, 40, 50};
int *ptr = arr; // 等同于int *ptr = &arr[0]
cout << *ptr; // 输出10
ptr++; // 移动到下一个int元素
cout << *ptr; // 输出20
2.2 指针与数组的等价性
在很多情况下,数组名可以当作指针使用:
cpp复制int arr[3] = {1, 2, 3};
cout << *(arr + 1); // 输出2,等同于arr[1]
但是,数组名和指针有一些重要区别:
- 数组名不是变量,不能重新赋值
- sizeof(数组名)返回整个数组的大小
- 数组名取地址(&arr)得到的是指向数组的指针,而不是指向第一个元素的指针
2.3 指针数组与数组指针
这两个概念经常让人混淆:
cpp复制int *ptrArray[10]; // 指针数组:包含10个int指针的数组
int (*arrayPtr)[10]; // 数组指针:指向包含10个int的数组的指针
3. 指针的高级用法
3.1 多级指针
指针可以指向另一个指针,形成多级指针:
cpp复制int var = 42;
int *ptr = &var;
int **pptr = &ptr;
cout << **pptr; // 输出42
3.2 函数指针
函数指针允许我们将函数作为参数传递或存储在数据结构中:
cpp复制int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int (*operation)(int, int); // 函数指针声明
operation = add;
cout << operation(5, 3); // 输出8
operation = subtract;
cout << operation(5, 3); // 输出2
3.3 动态内存分配
指针在动态内
