const 变量
初始化与推断已经解决了“值从哪里来”。程序中的上限、比例和阈值通常是规则,而不是运行时随意修改的状态。把它们写成常量,可以让名字表达意图,也让编译器阻止误修改。本章把运行时固定的值写成 const 常量,编译期确定的规则值和头文件共享由下一章的 constexpr 承担。
固定运行时值
const 变量必须在创建时初始化,创建后不能再赋值:
片段:常量的初始化与赋值
// 片段
int current_value{12};
const int kMaxCount{5};
// kMaxCount = 6; // 编译失败
current_value = 13; // 普通变量仍可修改const 表示“不能通过这个名字修改”,不等于对象在所有路径上永远不可变。先问这个值是否代表规则或不应变化的事实,再决定是否使用它。运行时才知道的配置仍然适用:例如从配置文件读入之后不再修改的限值,写成 const 就能防止后续误改。
命名常量
完整示例输出两个常量的值:
const-variables.cpp
#include <iostream>
int main() {
const int kMaxCount{5};
const int kTimeoutMs{3000};
std::cout << "最大数量: " << kMaxCount << "\n";
std::cout << "超时毫秒数: " << kTimeoutMs << "\n";
return 0;
}项目约定常量使用 k 加大驼峰,例如 kMaxCount。名字应说明含义和单位:kTimeoutMs 的 Ms 表明单位是毫秒,使用者不必再查文档确认 3000 是秒还是毫秒。比例、时间等带单位的数值都适合把单位写进名字。
常见错误
只声明不初始化 const
const int limit; 没有可用的初始值,会编译失败,常量的值必须在创建时给出。
浮点用于精确比较
需要精确计数或比较时优先使用合适的整数单位,比例等测量值才考虑 double,并在数值安全章节学习容差比较。
自测问题
为什么
const变量必须在创建时初始化?查看答案
没有初始值就没有获得值的机会,之后也不能通过赋值补救,这样的变量没有可用状态,编译器直接拒绝。
const保证对象在所有路径上永远不可变吗?查看答案
不保证。
const只约束“不能通过这个名字修改”,对象仍可能通过其他途径改变。先判断值是否代表规则,再决定是否使用。kTimeoutMs比kTimeout好在哪里?查看答案
单位写进了名字,使用者不必查文档确认
3000的含义,也降低了把秒当毫秒使用的概率。
本章回顾
你已经能把不会改变的值写成有意义的 const 常量,并理解初始化要求。示例见 const-variables.cpp,下一章说明 constexpr 与多个 .cpp 共享的头文件常量。