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

通过const_cast去除const后调用非const成员函数是否仅修改时触发UB?

问题

我想询问下述代码是仅当/* body */确实修改了i的值时才会触发未定义行为(UB),还是哪怕未进行修改,仅仅是对const对象调用非const成员函数maybeChange就会触发UB?

代码示例:

// header.hpp
struct Foo {
  int i;
  void maybeChange();
};

void work(Foo const& foo);
// foo.cpp
#include "header.hpp"
void Foo::maybeChange() {
  /* body */
}
// work.cpp
#include "header.hpp"
void work(Foo const& foo) {
  const_cast<Foo&>(foo).maybeChange();
}
// main.cpp
#include "header.hpp"
Foo const foo{6};

int main() {
  work(foo);
}

我理解当确实发生修改时会存在问题,因为这违反了编译器的合理假设——即全局对象foo不会被修改。但另一方面,C++标准中相关条款并未给出类似我上述示例的情况:通过const_cast去除const限定后对const对象调用非const成员函数但未实际修改对象的例子,仅给出了如下简单示例:

const int* ciq = new const int (3);     // initialized as required
int* iq = const_cast<int*>(ciq);        // cast required
*iq = 4;                                // undefined behavior: modifies a const object

其中最后一行确实修改了对象*ciq。

回答

仅当非const成员函数实际修改了const对象的内容时,才会触发未定义行为;如果只是调用非const成员函数但没有修改对象状态,并不会导致UB。

具体理由如下:

  • C++标准对const对象的核心约束是禁止修改其内容,而非禁止调用非const成员函数。非const成员函数只是语法上具备修改成员的权限,但如果函数体未实际修改任何成员,就没有违反const对象的不可修改性。
  • 编译器针对const对象的优化(比如将值视为常量缓存、省略读写操作等),只有当代码实际修改const对象时才会被打破,进而引发不一致的运行行为;若没有修改动作,这些优化不会产生问题。
  • 标准给出的示例重点指向“修改const对象”这一行为本身,而非const_cast或调用非const函数的动作——const_cast只是允许获取非const引用/指针,但后续是否触发UB完全取决于你用这个引用/指针执行了什么操作。

需要提醒的是:这种未修改的调用虽然本身合法,但属于极差的编码习惯。它会误导代码阅读者,且如果后续maybeChange的实现被修改为实际修改成员变量,就会悄无声息地引入未定义行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 20:13:15