C++ 常量指针与指针常量的实现示例
作者:yy__xzz
本文主要介绍了C++ 常量指针与指针常量的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
📚 前言:为什么要区分这两个概念?
很多C++初学者看到"常量指针"和"指针常量"这两个词就头晕,因为它们太像了!其实区分它们有一个简单口诀:
“左定值,右定向”(const在*左边,修饰的是指向的值;const在*右边,修饰的是指针本身)
第一章:基础概念图解
1.1 指针的两个属性
每个指针都有两个可以"恒定"的东西:
- 指针本身:指针变量存储的地址(指向哪里)
- 指向的值:通过指针访问的数据
第二章:代码解析
2.1 准备一个常量
const int i1 = 100; // 定义一个常量整数
理解:
i1是一个常量,值为100- 一旦定义,不能通过任何方式修改
i1的值 - 这为后面的例子提供了一个"只读"的数据源
2.2 常量指针(指向常量的指针)
const int* pi1 = &i1; // 指向常量的指针 // (*pi1)++; ❌ 指向的值不可修改
什么是常量指针?
常量指针 = 指针指向的值是常量,不能通过该指针修改
代码分析:
const int*:const在*左边,修饰的是int,表示"指向常量的指针"pi1指向i1(常量)- 尝试
(*pi1)++会编译错误,因为不能修改指向的值
2.3 另一种写法
int const* pi2 = &i1; // 同上,两种写法都表示常量指针 // (*pi2)++; ❌ 同样不能修改
为什么有两种写法?
const int* p; // 方法1:const在类型前 int const* p; // 方法2:const在类型后
这两种写法完全等价! 都表示"指向const int的指针"
记忆技巧:
- 无论
const在int前面还是后面,只要它在*左边,就是修饰指向的值 - 可以读作:
const int*= “不能修改int的指针”
2.4 指针常量(常量指针)
int* const pi3 = new int; // 指针本身是常量 // pi3++; ❌ 指针本身不能修改 // pi3 = new int; ❌ 不能指向别处 *pi3 = 200; ✅ 指向的值可以修改 delete pi3; // 释放内存
什么是指针常量?
指针常量 = 指针本身是常量,不能改变指向,但可以修改指向的值
代码分析:
int* const:const在*右边,修饰的是指针本身pi3一旦初始化,就不能再指向其他地址- 但通过
pi3修改指向的值是允许的
2.5 指向常量的常量指针
const int* const pi4 = &i1; // 指向和值都不能修改 // pi4 = new int; ❌ 指针本身不能修改 // *pi4 = 300; ❌ 指向的值不能修改
最强限定组合!
这个声明结合了前两者的特点:
- 第一个
const:指向的值是常量(在*左边) - 第二个
const:指针本身是常量(在*右边)
第三章:对比总结表
| 类型 | 声明方式 | 口诀 | 能否修改指向 | 能否修改值 | 示例 |
|---|---|---|---|---|---|
| 常量指针 | const int* p 或 int const* p | 左定值 | ✅ 可改 | ❌ 不可改 | p = &b; ✅ |
| 指针常量 | int* const p | 右定向 | ❌ 不可改 | ✅ 可改 | *p = 10; ✅ |
| 双重const | const int* const p | 都定 | ❌ 不可改 | ❌ 不可改 | 都不能改 |
第四章:记忆技巧大全
4.1 星号分割法
从*处把声明分成左右两部分:
const int * p // 左边是const int,右边是p int * const p // 左边是int,右边是const p
规则:
*左边的内容描述"指向的值"*右边的内容描述"指针本身"
4.2 英语阅读法
从右往左读:
const int* p:p is a pointer to const intint* const p:p is a const pointer to int
第五章:常见应用场景
5.1 常量指针的应用
场景:函数参数保护
void printArray(const int* arr, int size) {
for (int i = 0; i < size; i++) {
cout << arr[i] << " "; // 只能读取,不能修改
// arr[i] = 0; ❌ 编译错误,保护数组内容
}
}
int data[] = {1, 2, 3, 4, 5};
printArray(data, 5); // 安全传递,确保data不会被修改
5.2 指针常量的应用
场景:固定缓冲区地址
class Buffer {
int* const buffer; // 缓冲区地址固定
const int size; // 缓冲区大小固定
public:
Buffer(int s) : buffer(new int[s]), size(s) {}
void setValue(int index, int value) {
if (index < size) {
buffer[index] = value; // 可以修改内容
}
}
~Buffer() { delete[] buffer; }
};
5.3 双重const的应用
场景:只读配置项
class Config {
const char* const name; // 名称既不能改指向,也不能改内容
const int version; // 版本号常量
public:
Config(const char* n, int v) : name(n), version(v) {}
const char* getName() const { return name; }
int getVersion() const { return version; }
};
第六章:常见误区与练习
误区1:混淆声明顺序
const int* p; // 指向常量的指针 int const* p; // 也是指向常量的指针(容易误以为是指针常量) int* const p; // 这是指针常量!
误区2:以为const必须初始化
const int* p; // ✅ 可以,p可以先不指向任何东西 int* const p; // ❌ 错误!指针常量必须初始化! int* const p = &x; // ✅ 正确,必须初始化
误区3:通过转换绕过const
const int value = 100; const int* p = &value; int* q = const_cast<int*>(p); // 危险操作! *q = 200; // 未定义行为!value本来是常量
📝 动手练习
练习1:识别类型
int a = 10; int b = 20; // 分别说出下面这些指针的类型和特性 const int* p1 = &a; int* const p2 = &a; const int* const p3 = &a;
练习2:找出错误
int num = 5; const int* ptr1 = # int* const ptr2 = # ptr1 = &b; // 这行有问题吗? *ptr1 = 10; // 这行有问题吗? ptr2 = &b; // 这行有问题吗? *ptr2 = 10; // 这行有问题吗?
练习3:补全代码
void processData(__________ data, int size) {
// 函数需要保证不修改data指向的内容
for (int i = 0; i < size; i++) {
cout << data[i] << " ";
}
}
// 应该用什么类型作为参数?
答案
练习1答案:
p1:常量指针(指向的值不能改,但可以改指向)p2:指针常量(指向不能改,但可以改值)p3:双重const(都不能改)
练习2答案:
ptr1 = &b; // ✅ 可以,p1是常量指针,可以改指向 *ptr1 = 10; // ❌ 不可以,p1指向的值是常量 ptr2 = &b; // ❌ 不可以,p2是指针常量,不能改指向 *ptr2 = 10; // ✅ 可以,p2指向的值可以修改
练习3答案:
void processData(const int* data, int size) // 使用常量指针
总结:终极记忆法
| 声明 | 读法 | 能否改指向 | 能否改值 |
|---|---|---|---|
| const int* p | p是一个指向const int的指针 | ✅ | ❌ |
| int const* p | p是一个指向const int的指针 | ✅ | ❌ |
| int* const p | p是一个const指针,指向int | ❌ | ✅ |
| const int* const p | p是一个const指针,指向const int | ❌ | ❌ |
“const在左边,值是常量;const在右边,指针是常量”
到此这篇关于C++ 常量指针与指针常量的实现示例的文章就介绍到这了,更多相关C++ 常量指针与指针常量内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
