为什么我可以在constexpr函数中修改const_cast-ed对象?

我一直以为:

  • 写入const_casted 变量是 UB
  • constexpr 中不允许使用 UB

所以我很困惑为什么这段代码会编译:

constexpr int fn(){
    int v = 42;
    return [v]() {
        const_cast<int&>(v)+=5;
        return v;
    }();
}
static constexpr auto val = fn();
int main() {
    return val;
}

注意:我知道没有理由不允许这样做,因为结果应该是显而易见的,我对为什么允许这样做的法律解释更感兴趣。

回答

这部分是真的:

constexpr 中不允许使用 UB

这部分不是:

写入const_cast-ed 变量是 UB

实际规则是,来自[dcl.type.cv]/4:

任何在其生命周期 ([basic.life]) 期间修改 ([expr.ass], [expr.post.incr], [expr.pre.incr]) 的尝试都会导致 const 对象 ([basic.type.qualifier])在未定义的行为中。

请注意,相关部分是对象是否为const,而不是您到达它所采用的任何路径是否为const。在这种情况下,v不是const对象,也不是复制时在 lambda 中创建的对象。

但是,如果您声明vconst,那么在 lambda 中声明的那个也将被声明为const,因此尝试修改它将是未定义的行为。结果,您的代码将不再编译。


以上是为什么我可以在constexpr函数中修改const_cast-ed对象?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>