在 C++ 中,const
是一个非常强大的关键字,它用来限定不可修改性。合理使用 const
可以提高代码的安全性、可读性和维护性。
一、const
基本用法总结
使用位置 | 含义 |
---|---|
const int a = 10; |
常量,值不可修改 |
const int* p; |
指向常量的指针(不能改值) |
int* const p; |
常量指针(不能改地址) |
const int* const p; |
指向常量的常量指针 |
const 成员函数 |
该函数不修改成员变量 |
const 构造参数 |
防止拷贝/引用过程中被修改 |
二、在类中的 const
应用
1️⃣ const 成员函数
class Person {
std::string name;
public:
Person(const std::string& n) : name(n) {
}
std::string getName() const {
// const 成员函数
return name;
}
void setName(const std::string& n) {
name = n;
}
};
✅ const
成员函数保证:函数内不会修改任何成员变量。
如果你尝试修改 name
,编译器会报错:
std::string getName() const {
name = "New"; // ❌ 错误!不能在 const 函数中修改成员变量
return name;
}
2️⃣ const 成员变量(初始化列表中赋值)
class MyClass {
const int id; // 常量成员变量
public:
MyClass(int x) : id(x) {
} // 只能在初始化列表中赋值
};
注意事项:
const
成员变量必须通过 构造函数初始化列表 赋值;- 一旦设定不可更改。
3️⃣ 返回值为 const
class Person {
std::string name;
public:
const std::string& getName() const {
return name;
}
};
✔️ 返回 const std::string&
的好处是:调用者不能修改返回值:
Person p("Tom");
p.getName() = "Jerry"; // ❌ 报错:返回的是 const 引用,不能赋值
三、const 的应用场景推荐
使用 const 的最佳实践:
场景 | 示例 |
---|---|
不希望函数修改参数 | void func(const std::string& name) |
不希望函数修改成员变量 | int getX() const; |
提高表达力,增加自文档性 | const double pi = 3.14; |
避免不小心改写数据 | 尤其是当参数是引用或指针时 |
四、容易混淆的写法
const int* p; // 指向 const int —— 可以改指针地址,不能改值
int* const p; // const 指针 —— 可以改值,不能改地址
const int* const p; // 两个都不能改
例子说明:
int a = 10;
int b = 20;
const int* p1 = &a; // *p1 = 20; ❌ 不允许
p1 = &b; // ✅ 允许修改地址
int* const p2 = &a; // p2 = &b; ❌ 不允许
*p2 = 30; // ✅ 允许修改值
五、const 与重载
const
成员函数和非 const
版本可以共存,形成重载。
class Test {
public:
int value = 10;
int& get() {
// 非 const 版本
return value;
}
int get() const {
// const 版本
return value;
}
};
这样就可以:
Test t1;
t1.get() = 100; // ✅ 可以修改
const Test t2;
int x = t2.get(); // ✅ 调用 const 版本
六、小结
位置 | 意义 |
---|---|
参数前 const |
函数不修改参数 |
成员函数后 const |
函数不修改类成员 |
返回值加 const |
保证调用者不能修改返回对象 |
成员变量 const |
必须在构造时初始化 |
指针位置不同的 const |
控制是否能修改地址或值 |