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
相关产品推荐
相关产品推荐

