gpt4 book ai didi

c++ - 初始化程序中的多个突变是否列出了未定义的行为?

转载 作者:IT老高 更新时间:2023-10-28 21:47:48 26 4
gpt4 key购买 nike

我对初始化列表和序列点很好奇。不久前我读到初始化列表中的评估顺序是从左到右的。如果是这样,那么评估点之间肯定有某种序列点,我错了吗?那么说的是以下有效代码吗?有什么会导致未定义的行为吗?

int i = 0;

struct S {
S(...) {}
operator int() { return i; }
};

int main() {
i = S{++i, ++i};
}

感谢所有回复。

最佳答案

是的,代码是有效的并且没有未定义的行为。初始化器列表中的表达式在 S 的构造函数求值之前从左到右求值并排序。因此,您的程序应始终将值 2 分配给变量 i

引用 C++ 标准的第 8.5.4 节:

“在一个花括号初始化列表的初始化器列表中,初始化器子句,包括任何由包扩展 (14.5.3) 产生的子句,按照它们出现的顺序进行评估 。也就是说,与给定初始化子句关联的每个值计算和副作用在每个值计算和副作用之前排序> 与初始化器列表的逗号分隔列表中的任何初始化器子句相关联。"

因此,发生的事情是:

  1. ++i 被求值,产生 i = 1(S 的构造函数的第一个参数);
  2. ++i 被求值,产生 i = 2(S 的构造函数的第二个参数);
  3. S的构造函数被执行;
  4. S的转换运算符被执行,返回值2;
  5. 2 被分配给 i(它已经有值 2)。

该标准的另一个相关段落是第 1.9/15 节,其中还提到了确实具有未定义行为的类似示例:

i = v[i++]; // the behavior is undefined
i = i++ + 1; // the behavior is undefined

但是,同一段说:

"除非另有说明,单个运算符的操作数和单个表达式的子表达式的计算是无序的。[...]调用函数时(无论函数是否内联),与任何参数表达式相关的每个值计算和副作用,或与指定被调用函数的后缀表达式相关,都在被调用函数主体中的每个表达式或语句执行之前排序。"

因为 1) 初始化器列表中表达式的求值顺序是从左到右,2) S 的构造函数的执行顺序在初始化器中的所有表达式求值之后列表,以及 3) i 的赋值是在 S 的构造函数(及其转换运算符)执行之后排序的,行为是明确定义的。

关于c++ - 初始化程序中的多个突变是否列出了未定义的行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14442894/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com