1. 引言
在c++编程中,const关键字与指针的结合使用是初学者容易混淆的概念之一。特别是“常量指针”和“指针常量”这两个术语,它们虽然听起来相似,但含义和用法却截然不同。理解它们的区别对于编写安全、高效的c++代码至关重要。本文将结合详细的代码示例,深入剖析这两个概念,帮助你彻底掌握它们。
2. 基本概念与语法
首先,我们需要明确两个核心概念的定义:
- 常量指针(pointer to constant):指针指向的内容是常量,不能通过该指针修改所指向的值,但指针本身可以指向其他地址。
- 指针常量(constant pointer):指针本身是常量,一旦初始化后就不能再指向其他地址,但可以通过该指针修改所指向的值。
语法上的区别在于const关键字的位置:
// 常量指针:const在类型前或类型后,但在*前 const int* ptr1; // 方式一 int const* ptr2; // 方式二(与方式一等价) // 指针常量:const在*后 int* const ptr3; // 指针本身是常量
3. 常量指针(pointer to constant)
常量指针意味着“指向常量的指针”。指针可以改变指向,但不能通过这个指针修改它所指向的值。
3.1 基本用法
#include <iostream>
using namespace std;
int main() {
int value1 = 10;
int value2 = 20;
// 声明一个常量指针
const int* ptr = &value1;
// 可以读取指向的值
cout << "*ptr = " << *ptr << endl; // 输出: 10
// ❌ 错误:不能通过ptr修改value1
// *ptr = 30; // 编译错误
// ✅ 正确:可以让ptr指向其他变量
ptr = &value2;
cout << "*ptr = " << *ptr << endl; // 输出: 20
// 即使value2本身不是const,也不能通过ptr修改
value2 = 30; // 直接修改value2是可以的
cout << "value2 = " << value2 << endl; // 输出: 30
cout << "*ptr = " << *ptr << endl; // 输出: 30
return 0;
}3.2 实际应用场景
常量指针常用于函数参数,表示函数不会修改传入指针所指向的数据:
// 安全:函数承诺不修改str的内容
void printstring(const char* str) {
// str[0] = 'a'; // ❌ 编译错误
cout << str << endl;
}
// 安全:函数承诺不修改arr的元素
int sumarray(const int* arr, int size) {
int sum = 0;
for (int i = 0; i < size; i++) {
// arr[i] = 0; // ❌ 编译错误
sum += arr[i];
}
return sum;
}4. 指针常量(constant pointer)
指针常量意味着“指针本身是常量”。指针一旦初始化后就不能再指向其他地址,但可以通过这个指针修改它所指向的值。
4.1 基本用法
#include <iostream>
using namespace std;
int main() {
int value1 = 10;
int value2 = 20;
// 声明一个指针常量,必须初始化
int* const ptr = &value1;
// ✅ 正确:可以通过ptr修改value1
*ptr = 30;
cout << "value1 = " << value1 << endl; // 输出: 30
// ❌ 错误:不能让ptr指向其他变量
// ptr = &value2; // 编译错误
// 注意:value1本身不是const,可以直接修改
value1 = 40;
cout << "*ptr = " << *ptr << endl; // 输出: 40
return 0;
}4.2 实际应用场景
指针常量常用于需要固定指向某个对象的场景,比如类的成员指针:
class buffer {
private:
char* const buffer; // 指针常量,指向固定内存
int size;
public:
buffer(int sz) : buffer(new char[sz]), size(sz) {
// buffer在构造函数中初始化后就不能再改变
}
~buffer() {
delete[] buffer;
}
void fill(char c) {
for (int i = 0; i < size; i++) {
buffer[i] = c; // ✅ 可以修改buffer指向的内容
}
}
// ❌ 不能在成员函数中改变buffer的指向
// void resize(int newsize) {
// buffer = new char[newsize]; // 编译错误
// }
};5. 双重常量:指向常量的指针常量
当const同时出现在类型前和*后时,就形成了“指向常量的指针常量”,既不能修改指针的指向,也不能通过指针修改所指向的值。
#include <iostream>
using namespace std;
int main() {
int value = 100;
// 指向常量的指针常量
const int* const ptr = &value;
// ✅ 正确:可以读取值
cout << "*ptr = " << *ptr << endl; // 输出: 100
// ❌ 错误:不能通过ptr修改value
// *ptr = 200; // 编译错误
// ❌ 错误:不能让ptr指向其他变量
// int another = 300;
// ptr = &another; // 编译错误
// 注意:value本身不是const,可以直接修改
value = 200;
cout << "*ptr = " << *ptr << endl; // 输出: 200
return 0;
}6. 记忆技巧与对比总结
6.1 快速记忆法
记住这个简单的规则:const在*左边修饰的是指向的内容,const在*右边修饰的是指针本身。
const int* p; // const在*左边:指向的内容是常量 int* const p; // const在*右边:指针本身是常量 const int* const p; // 两边都有const:内容和指针都是常量
6.2 对比表格
| 类型 | 语法 | 能否修改指针指向 | 能否通过指针修改值 | 典型用途 |
|---|---|---|---|---|
| 常量指针 | const int* p 或 int const* p | ✅ 可以 | ❌ 不可以 | 函数参数,保护数据不被修改 |
| 指针常量 | int* const p | ❌ 不可以 | ✅ 可以 | 固定指向某个对象,如类成员指针 |
| 双重常量 | const int* const p | ❌ 不可以 | ❌ 不可以 | 完全只读的指针,如全局配置 |
6.3 常见错误示例
// 错误1:混淆概念 int a = 5, b = 10; const int* p1 = &a; // *p1 = 6; // ❌ 错误:不能通过p1修改a int* const p2 = &a; // p2 = &b; // ❌ 错误:不能改变p2的指向 // 错误2:类型不匹配 const int x = 100; // int* p3 = &x; // ❌ 错误:不能用普通指针指向const变量 const int* p4 = &x; // ✅ 正确:需要用常量指针 // 错误3:多级指针 const int** pp1; int* p5; // pp1 = &p5; // ❌ 危险:可能通过*pp1修改const内容 // 正确做法:使用相同const限定 const int* p6; pp1 = &p6; // ✅ 正确
7. 实际编程建议
- 优先使用常量指针:在函数参数中,除非确实需要修改指针指向的内容,否则应该使用
const t*,这可以提高代码的安全性和可读性。 - 明确指针常量的用途:当需要确保指针始终指向同一个对象时,使用指针常量。这在资源管理(如智能指针)和类设计中很有用。
- 注意const传播:在多层指针或引用中,const的传播规则需要仔细考虑,避免意外的类型转换错误。
- 使用类型别名简化:对于复杂的指针类型,可以使用
typedef或using来简化:
using constintptr = const int*; // 常量指针 using intconstptr = int* const; // 指针常量 using constintconstptr = const int* const; // 双重常量
8. 总结
理解常量指针和指针常量的区别是掌握c++指针和const用法的关键。简单来说:
- 常量指针:保护的是指针指向的数据,不保护指针本身。
- 指针常量:保护的是指针本身,不保护指针指向的数据。
- 双重常量:既保护指针指向的数据,也保护指针本身。
在实际编程中,根据需求选择合适的类型,可以让代码更加安全、清晰。记住const的位置决定了它修饰的对象,这是理解这一概念的核心。
到此这篇关于c++中常量指针与指针常量的区别的文章就介绍到这了,更多相关c++ 常量指针与指针常量内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论