You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中const修饰普通类型与指针赋值行为差异问题

问题场景

第一段代码编译时会在第(4)行报错,提示无法将Fruit类型赋值给const Fruit类型:

(1) Fruit f1{"Orange"};
(2) Fruit f2{"Lemmon"};
(3) const Fruit ff = f1;
(4) ff = f2;

将代码改为指针写法后,第(4)行不会触发编译错误:

(1) Fruit f1{"Orange"};
(2) Fruit f2{"Lemmon"};
(3) const Fruit* ff = &f1;
(4) ff = &f2;
原因解释

两种写法的核心差异是const的修饰目标完全不同,对应C++中顶层const和底层const的区别:

  • 第一段代码中const Fruit ff = f1的const是顶层const,修饰的是变量ff本身:即ff这个对象自身是常量,初始化完成后不允许再被赋值修改,因此第(4)行给ff重新赋值的操作直接违反常量约束,编译器必然报错。
  • 第二段代码中const Fruit* ff = &f1的const是底层const,修饰的是指针ff指向的目标对象,而非指针变量ff自身:这个定义的语义是「ff是一个指向const Fruit类型的指针」,仅约束不能通过ff指针修改它指向的Fruit对象,但指针变量ff本身是没有const修饰的普通变量,自然可以被重新赋值,指向其他兼容类型的内存地址。

另外,C++标准明确允许Fruit*到const Fruit*的隐式转换:这个转换只是给指针增加了「不可通过该指针修改指向内容」的限制,本质是把可修改对象的地址交给一个承诺“不会通过这个地址改值”的指针,不存在违反const约束的风险,编译器不会拦截。

如果要让第二段代码里的指针自身也不可修改,需要把const写在*的右侧,也就是定义为Fruit* const ff = &f1;,这时候再执行ff = &f2;就会和第一段代码一样触发编译错误——因为此时const修饰的是指针变量ff本身,它是一个不能被重新赋值的常量。

快速判断const修饰对象的规则:const出现在*左侧时,修饰的是指针指向的内容;const出现在*右侧时,修饰的是指针变量本身。

内容的提问来源于stack exchange,提问作者rdabra

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 23:57:16