C++ 函数调用的“未定义”与“未指定”行为:f(i=-2, i=-2) 不再是未定义 vs f(++i, ++i) 未指定

问题描述 投票:0回答:1

我知道这是那些“未定义的行为”问题之一,但是有关该主题的当前 cppreference 页面(从 C++23 开始)本身给出了两个示例,我无法从其排序规则中理解它们:

f(i = -2, i = -2); // undefined behavior until C++17
f(++i, ++i);       // undefined behavior until C++17, unspecified after C++17

即,两个示例的两个问题:

    1. 为什么从 C++17 开始不“未定义”(对于第一个示例)?
    1. 为什么从 C++17 开始使用“未指定”而不是“未定义”(对于第二个示例)?

上面给出的 C++ cppreference 页面给出了一个关于函数参数排序的规则,我可以在这里看到它:

  1. 在函数调用中,每个参数初始化的值计算和副作用相对于任何其他参数的值计算和副作用是不确定地排序的。
  1. 那么为什么
    f(i = -2, i = -2);
    不是未定义的呢? C++17 是否添加了语言来指定如果无论参数的求值顺序如何都会出现相同的结果,则它不是未定义的?
  2. 这两个示例之间有什么不同导致
    f(++i, ++i);
    的“未指定”而不是简单地未定义?
c++ c++17 undefined-behavior function-call unspecified-behavior
1个回答
0
投票

但是当前的 C++ 规范

这不是 C++ 规范。这是一个令人惊奇且伟大的网站,名为“cppreference”。我们通常在线使用 C++ 标准草案 https://eel.is/c++draft/ 。实际的 C++ 标准必须购买 https://www.iso.org/standard/79358.html .

为什么 f(i = -2, i = -2);不是未定义吗?

因为正如您引用的那样,它的顺序不确定。

C++17 是否添加了语言来指定如果无论参数的求值顺序如何都会出现相同的结果,则它不是未定义的?

是的。 cppreference 有:

A 和 B 的计算顺序不确定:它们可以按任何顺序执行,但不能重叠:要么 A 在 B 之前完成,要么 B 在 A 之前完成。下次相同的表达式时,顺序可能相反已评估。

如果评估是无序的,那么这是未定义的行为。在 cppreference 中:

如果某个内存位置上的副作用相对于同一内存位置上的另一个副作用来说是无序的,则该行为是未定义的。

这两个示例之间有什么不同导致 f(++i, ++i); 出现“未指定”情况

因此,在

f(i = -2, i = -2);

 中,无论 
i = -2
 先发生,都会调用 
f(-2, -2)

f(++i, ++i)

中,这取决于
++
何时发生与评估
i
..从
i = 0
开始,您可以获得
f(0, 0)
f(0, 1)
f(1, 0)

© www.soinside.com 2019 - 2024. All rights reserved.