c++中,const(常量限定符)的核心作用时 声明“不可修改”的实体 ,前置编译器保证“只读性”。可以修饰变量、指针、引用、成员函数、函数参数/返回值等。
一、核心思想
const的本质是“编译期间检查的制度契约”:
- 被
const修饰的实体, 编译阶段不允许通过该实体修改其值 (运行时仍然可能通过其他非const途径修改,除非是编译时常量); - 违反契约会直接编译报错而非运行时错误,提前规避bug
二、const的常见用法
1.修饰普通变量(常量)
最基础的用法:声明“不可修改的变量”, 必须初始化(否则编译报错)。
const int max_size = 100; // 正确:编译期常量,不可修改
max_size = 200; // 错误:const 变量不能被赋值
// 注意:const 变量的作用域与普通变量一致,全局 const 默认内部链接(需 extern 显式声明外部链接)
与#define的区别(关键)
const变量是类安全的,而#define是文本替换(无类型、无作用域):
const int a = 3; #define B 3
int x = a + 1; // 编译时已知 a=3,可优化
int y = B + 1; // 预处理替换为 3+1,无类型检查
// 若 #define B "3",则 y = "3"+1 会编译报错,但 #define 本身不做类型校验
2.修饰指针
(1)指向常量的指针(const T* p)
const修饰指针指向的内容:内容不可改,指针本身可改(可指向其他地址)。
int a = 10, b = 20;
const int* p = &a; // p 指向 a,a 的值不能通过 p 修改
*p = 30; // 错误:不能通过 p 修改指向的内容
p = &b; // 正确:指针 p 可指向其他地址
(2)常量指针(T* const p)
const修饰指针变量本身:指针不可变(不能指向其他地址),指向的内容可修改。
int a = 10, b = 20;
int* const p = &a; // p 是常量指针,必须初始化(指向 a)
p = &b; // 错误:指针 p 不能指向其他地址
*p = 30; // 正确:可通过 p 修改 a 的值(a 本身非 const)
(3)指向常量的常量指针(const T* const p)
const同时修饰”内容“和”指针“:两者都不可以修改。
const int* const p = &a;
*p = 30; // 错误:内容不可改
p = &b; // 错误:指针不可改
记忆技巧:
const靠近谁,谁就不可以修改:
const T* p-const靠近T(内容) - 内容不可以修改;T* const p-const靠近p(指针) - 指针不可以修改。
3.修饰引用(常量引用const T&)
const修饰引用时,声明‘不能通过该引用修改被引用的对象’,核心用途:
- 避免拷贝(传递大对象时高效,如
std::string、自定义类); - 保护实参(防止函数内部意外修改实参)
void print(const std::string& s) {
// s += "test"; // 错误:const 引用不能修改被引用对象
std::cout << s << std::endl;
}
int main() {
std::string str = "hello"; print(str); // 实参 str 不会被修改,且无拷贝开销
// 常量引用还能绑定临时对象(普通引用不能)
print("world"); // 正确:临时字符串 "world" 绑定到 const 引用
return 0;
}
4.修饰类的成员函数(double number_value() const;)
最常用的场景之一:声明常成员函数,核心规则:
- 常成员函数不能修改类的非静态数据成员;
- 常成员函数不能调用类的非const成员函数(只能调用const成员函数);
- 成员函数的
this指针式const T*类型(普通成员函数的this是T*),因此无法通过this修改成员变量。
示例解析
class Number {
private:
double value = 3.14; // 非静态数据成员
public:
// 常成员函数:承诺不修改对象状态
double number_value() const {
// value = 5.20; // 错误:不能修改非静态成员变量
return value; // 正确:只读访问成员变量
}
void set_value(double v) { // 非 const 成员函数:可修改对象
value = v;
}
};
关键用法:常对象只能调用常成员函数
- 普通对象(
Numbew obj):可到用 const 和非 const 成员函数; - 常对象(
const Number obj):只能调用 const 成员函数(因为对象本身不可修改,非 const 成员函数可能修改对象)。
int main() {
Number obj1; // 普通对象
obj1.number_value(); // 正确(调用 const 成员函数)
obj1.set_value(2.71); // 正确(调用非 const 成员函数)
const Number obj2; // 常对象
obj2.number_value(); // 正确(常对象只能调用 const 成员函数)
// obj2.set_value(1.68); // 错误:常对象不能调用非 const 成员函数
return 0;
}
例外:mutable修饰的成员变量
若成员变量被 mutable 修饰,则即使在常成员函数中,也可修改该变量(mutable 意为 “可变的”,打破 const 限制,通常用于计数、缓存等不影响对象核心状态的场景):
class Number {
private: mutable int call_count = 0; // mutable 成员:可在 const 函数中修改
double value = 3.14;
public: double number_value() const {
call_count++; // 正确:mutable 成员可修改
return value;
}
};
5.修饰函数参数(void func(const T param))
作用:限制函数内部不能修改参数,保护实参(尤其当参数是引用/指针时)
// 1. 传值参数:const 意义不大(参数是拷贝,修改不影响实参)
void func1(const int x) {
// x = 10; // 错误:不能修改 const 参数
}
// 2. 传引用/指针参数:意义重大(避免拷贝 + 保护实参)
void func2(const std::vector<int>& vec) {
// vec.push_back(1); // 错误:不能修改实参
}
6.修饰函数返回值(const T func())
- 若返回值是传值(如
const int func()):意义不大(返回值是临时对象,本身不可修改); - 若返回值是指针/引用(如
const int& func()):限制调用者不能通过返回值修改原独享,避免悬垂引用/指针。
class Number {
private: int data = 10;
public:
const int& get_data() const { // 返回 const 引用
return data;
}
};
int main() {
Number obj;
// obj.get_data() = 20; // 错误:const 引用返回值不能被修改
return 0;
}
1697

被折叠的 条评论
为什么被折叠?



