c++ const pointer
在 C/C++ 中,const
关键字与指针结合使用时,会产生不同的效果,主要是 const 指针 和 指向 const 的指针 两种情况。这两者在语法、含义和使用场景上有着明显的区别。以下是对这两种指针的详细讲解:
1. 指向 const 的指针
定义:指向 const
对象的指针,表示指针指向的内存中的数据是只读的(不能通过该指针修改)。但指针本身的值(即指向的地址)是可以改变的。
语法:
const T *ptr; // 或 T const *ptr;
T
是数据类型(如int
,char
等)。const
修饰的是*ptr
,表示指针指向的内容是常量。- 这种指针可以指向任何
T
类型的数据(包括非const
数据),但通过该指针无法修改指向的数据。
特点:
- 不能通过指针修改指向的数据:
*ptr = value
会导致编译错误。 - 指针本身可以改变:可以让
ptr
指向其他地址。 - 可以指向非 const 数据:即使指向非
const
数据,也只能以只读方式访问。
示例代码:
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
const int *ptr = &a; // 指向 const 的指针
// *ptr = 15; // 错误:不能通过 ptr 修改 a 的值
ptr = &b; // 正确:可以改变 ptr 指向的地址
printf("%d\n", *ptr); // 输出 20
return 0;
}
使用场景:
- 当函数参数需要传递指针,但不希望通过该指针修改数据时,常用
const T *
。
例如:void printValue(const int *p) { // *p = 100; // 错误:不能修改 printf("%d\n", *p); }
2. const 指针
定义:指针本身是常量,表示指针的地址不可改变(即不能指向其他地址),但指针指向的数据是可以修改的(如果数据本身不是 const
)。
语法:
T * const ptr = &some_variable;
const
修饰的是ptr
,表示指针本身是常量。- 必须在定义时初始化,因为
const
指针不能重新赋值。 - 通过该指针可以修改指向的数据(只要数据本身不是
const
)。
特点:
- 指针的地址不可变:不能让
ptr
指向其他地址。 - 可以通过指针修改数据:
*ptr = value
是合法的(如果数据本身不是const
)。 - 必须初始化:定义
const
指针时必须指定初始地址。
示例代码:
#include <stdio.h>
int main() {
int a = 10;
int b = 20;
int * const ptr = &a; // const 指针
*ptr = 15; // 正确:可以修改 a 的值
// ptr = &b; // 错误:不能改变 ptr 的指向
printf("%d\n", *ptr); // 输出 15
return 0;
}
使用场景:
- 当需要确保指针始终指向同一地址,但允许修改该地址的数据时使用。
- 例如,固定指向某个全局变量或数组的指针。
3. const 指针指向 const 数据
定义:结合上述两种情况,指针本身是常量,且指向的数据也是常量。
语法:
const T * const ptr = &some_variable;
- 第一个
const
修饰*ptr
,表示不能通过指针修改数据。 - 第二个
const
修饰ptr
,表示指针本身不能改变指向。 - 必须在定义时初始化。
特点:
- 指针不可变:不能让
ptr
指向其他地址。 - 数据不可变:不能通过
ptr
修改指向的数据。 - 提供最高级别的限制,适用于完全不可修改的场景。
示例代码:
#include <stdio.h>
int main() {
int a = 10;
const int * const ptr = &a; // const 指针指向 const 数据
// *ptr = 15; // 错误:不能修改数据
// ptr = &b; // 错误:不能修改指针
printf("%d\n", *ptr); // 输出 10
return 0;
}
使用场景:
- 当需要完全锁定指针及其指向的数据时使用,例如在嵌入式系统中操作硬件寄存器。
4. 总结与对比
类型 | 语法 | 指针地址可变 | 数据可通过指针修改 | 使用场景示例 |
---|---|---|---|---|
指向 const 的指针 | const T *ptr | 是 | 否 | 函数参数传递,保护数据不被修改 |
const 指针 | T * const ptr | 否 | 是(非 const 数据) | 固定指针指向的地址 |
const 指针指向 const | const T * const ptr | 否 | 否 | 完全锁定指针和数据,硬件寄存器 |
5. 记忆技巧
- 阅读顺序:从右到左读指针声明:
const int *ptr
:*ptr
是const int
,即指针指向的是常量int
。int * const ptr
:ptr
是const
,即指针本身是常量。const int * const ptr
:*ptr
是const int
,且ptr
是const
,两者都不可变。
- const 位置:
const
在*
之前,修饰的是指向的数据。const
在*
之后,修饰的是指针本身。
6. 注意事项
- 指向非 const 数据的 const 指针:
const int *ptr
可以指向int
或const int
,但不能通过ptr
修改数据。- 反过来,
int *ptr
不能指向const int
(会丢失const
限定)。
- const 指针的初始化:
T * const ptr
必须在定义时初始化,否则无法使用。
- 多级指针:
- 对于多级指针(如
int **ptr
),const
可以修饰每一级,规则类似。例如:const int **ptr; // 指向 const int* 的指针 int * const *ptr; // 指向 int* 的 const 指针
- 对于多级指针(如
7. 实际应用
- 函数参数:
const T *
常用于函数参数,防止函数修改传入的数据。例如strlen(const char *str)
。 - 类成员函数:在 C++ 中,
const
指针常用于类成员函数的参数或返回值,以保护对象状态。 - 嵌入式系统:
const T * const
常用于硬件寄存器操作,确保地址和数据都不被意外修改。
如果有更具体的代码或场景需要分析,请提供,我可以进一步讲解!