为什么游戏里你的金币会变,而圆周率永远不变?——变量与常量的本质区别
你有没有遇到过这种情况?玩闯关游戏时,你的生命值一会儿满格,一会儿见底——甚至在一局中反复横跳。而游戏里的物理法则,比如重力加速度、跳跃的力度曲线,却像铁律一样从不改变。这种“变”与“不变”,恰好对应了编程世界的两个核心概念:变量和常量。
你可能觉得这很简单:变量就是能改的,常量就是不能改的。但真写代码时,很多人会栽在“该用常量却用了变量”或“常量被意外修改”这种坑里。今天我们就彻底掰开揉碎,搞清楚这两个东西背后的设计逻辑,以及怎么用它们写出既灵活又安全的代码。
变量:数据世界的“储物盒”
想象你有一个塑料储物盒,上面贴了张标签“age”。你往里面放了一个数字10。过一会儿,你觉得不对,打开盒子把10换成11。盒子还是那个盒子,标签没变,但里面的东西变了。这就是变量——一个名字对应一块内存空间,里面的值可以随时替换。
在C++里,使用变量前要先声明它的类型和名字,就像告诉电脑:“我要一个叫age的盒子,它只能装整数”。然后你可以给它一个初始值,也可以之后再赋值:
int age = 10; // 声明并初始化
age = 11; // 修改值
这里关键点在于:变量必须先声明,后使用。如果你直接写 age = 11; 而前面没有 int age;,编译器会报错,因为它不知道 age 是什么类型的盒子。
常量:带锁的铁箱子
常量则像一只铁箱子,你放进去一样东西,箱子“咔嗒”一声自动锁死,从此再也打不开。所以常量的值一旦确定,整个程序生命周期内都不能再改。
C++中用 const 关键字来定义常量:
const int DAYS_IN_WEEK = 7; // 一周有7天,永远不会变
// DAYS_IN_WEEK = 8; // 编译错误:常量不能被修改
注意:常量的命名习惯是全大写加下划线,比如 DAYS_IN_WEEK。这虽然不是语法强制,但几乎所有C++程序员都遵循这个约定,让你一眼就能看出这是个无法修改的值。
一道题看出“声明”有多重要
来看一个典型题目:
在C++中,以下哪条语句正确地声明了一个整型变量并初始化为10?
选项可能长得差不多,但关键点在于:声明和初始化能不能合在一行。正确的写法就是 int age = 10;。有人说 int age; age = 10; 也对——没错,那是“先声明后赋值”,不是“声明并初始化”。题目要求的是“声明并初始化”,所以只有第一条符合。
这道题考察的正是变量声明的语法格式:类型 + 变量名 + 初始值(可选)。很多人写代码时容易忘记分号,或者写成 int age(10);(在C++里也能工作,属于另一种初始化方式,但题目通常默认用等号初始化)。理解“声明”是告诉编译器“我要一个盒子”,而“初始化”是“第一次往盒子里放东西”,这两者可以绑定在一起。
再来看常量的“铁律”
另一个题目:
在C++中,使用const关键字定义的常量在程序运行过程中可以被修改。
判断对错。显然这是错误的。常量一旦初始化,就不能再变。这道题看似简单,但隐藏着一个常见误解:有人觉得 const 只是在编译时检查,运行时可以通过指针或引用修改。实际上,现代C++中 const 是严格的承诺,任何试图修改 const 对象的行为都会导致未定义行为,编译器也会拦截。
比如:
const int X = 5;
int* p = (int*)&X; // 强制转型,危险!
*p = 10; // 试图修改常量——未定义行为
代码可能编译通过,但运行时可能崩溃或产生奇怪结果。所以永远不要尝试绕过 const 的约束——这就像有人用撬棍去撬那个铁箱子,就算撬开了,箱子也废了。
为什么我们要区分“可变”和“不可变”?
这个问题我思考了很久。单纯从语法上讲,你可以把所有数据都定义成变量,随时改。但为什么要有常量?
第一,安全。某些值比如圆周率 3.14159、一年12个月、游戏里的最大生命值上限,如果你不小心改了,整个程序的逻辑就崩了。用 const 相当于给这些值上了一把锁,连你自己都不能改——这反而保护了你。
第二,可读性。其他程序员看到 const double PI = 3.14159; 一眼就知道“哦,这个值不该变”。如果写成 double pi = 3.14159;,别人就会怀疑:“这个 pi 会不会在后面被修改?”
第三,编译器优化。编译器知道 const 变量不会被修改,可以做更激进的优化,比如直接把值嵌入到机器码里,而不是每次从内存读取。
实际场景中如何选择?
想想你的游戏:角色的金币数会变 → 用变量 int gold = 100;。而游戏里每周任务奖励的固定倍数(比如日常奖励是100金币,周常奖励是500金币)→ 用常量 const int DAILY_REWARD = 100;。这样后续想调整奖励时,只需要改一个地方,而不会误伤其他地方。
再举个例子:你的年龄 → 变量。数学上的圆周率 → 常量。你玩的游戏里角色的生命值上限(比如100点)→ 常量,因为它是固定值;而当前生命值 → 变量,因为会受伤回血。
进阶思考
变量和常量的区别看似基础,但背后是计算机科学中“可修改性”的核心思想。当你学到 const 引用、const 成员函数、constexpr(编译期常量)时,会发现这个概念延伸出大量设计模式。比如“尽量使用常量”是很多C++大牛的原则:能用 const 的地方就用 const,这样编译器能帮你抓住很多低级错误。
如果你已经掌握了基础,可以试着思考:为什么C++中数组的长度必须是常量?为什么 const 变量可以用作数组大小,而普通变量不行?这背后涉及到编译器在编译期需要知道内存布局——常量在编译期就已知,变量则要到运行时才确定。这些深入的知识会让你对编程语言的设计有更深刻的理解。
关于作者
我是赵老师,持有 NOI 信息学奥赛教练证书,拥有 15 年以上的软件开发经验,从事信息学少儿编程教学已有 8 年时间。
这些年累计帮助 多名 学生通过编程特长升入自己心仪的目标学校。
如果你在编程学习上有任何疑问,欢迎联系我:18620372957(微信同号)