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

常量表达式上下文中的对象修改规则疑问

C++常量表达式对象修改规则的理解误区
struct S
{
  constexpr S(){};
  constexpr S(const S &r) { *this = r; };
  constexpr S &operator=(const S &) { return *this; };
};

int main()
{
  S s1{};
  constexpr S s2 = s1; // 编译器判定合法
}

上述程序是合法的,但你认为它应该违反常量表达式规则。根据C++标准条款[expr.const]/(5.16):

表达式E是核心常量表达式,除非其按照抽象机规则求值时出现下列情况之一:

  • [...]
  • (5.16) 对象的修改,除非修改的是字面类型的非易失性左值,且该左值指代的非易失性对象的生存期始于E的求值过程中;
  • [...]

你的理解误区在于搞错了核心常量表达式E的范围,以及被修改的对象是谁:

  1. 这里的E不是s1,而是初始化constexpr对象s2的整个表达式——也就是拷贝构造函数的调用过程。
  2. 拷贝构造函数里的*this = r;修改的是正在构造的s2(*this指代的是s2),而不是s1。s2的生存期正是在这个常量表达式E的求值过程中开始的,完全满足条款中的例外条件。
  3. s1在整个过程中只是被读取,并没有被修改,所以根本不触发[expr.const]/(5.16)的禁止条件。

简单来说,你误以为修改的是s1,但实际修改的是新对象s2,而s2的生存期始于常量表达式求值期间,符合规则,因此程序合法。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 12:15:42