5

根据 C++03 标准 1.9/5

执行格式良好的程序的一致实现应产生与具有相同程序和相同输入的抽象机的相应实例的可能执行序列之一相同的可观察行为。

我没有得到“作为之一”的部分。

如果我有一个特定的程序和一个特定的输入,并且我的程序不包含未定义的行为,为什么可观察到的行为会有所不同?“可能的执行顺序之一”是什么意思?

4

4 回答 4

12

在 C++ 中,某些事情留给实现。例如,当你写

int x = f(a) + f(b);

实现可以选择先调用 f(a) 或先调用 f(b)。

于 2012-07-19T13:56:42.010 回答
8

考虑:

x = f() + g();

这允许两种可能的执行顺序:

__temp1 = f();           /*or*/     __temp1 = g();
__temp2 = g();           /*or*/     __temp2 = f();
x = __temp1 + __temp2;   /*or*/     x = __temp2 + __temp1;

该标准没有规定必须执行哪些;只是程序必须表现得好像执行了这两个之一。如果f()并且g()有副作用,那么程序可能具有两种不同的可观察行为之一。

于 2012-07-19T13:57:00.713 回答
3

C++ 标准没有定义某些表达式的求值顺序。例如,在:

    proc( a(), b() );

a() 和 b() 都必须在 proc() 之前求值,但 a() 可以在 b() 之前或之后求值。所以有两个合法的执行序列,如果 a() 和 b() 有副作用(例如,打印语句),你可以知道使用了哪个编译器。

(这种关于评估顺序的自由旨在帮助编译器生成更有效的代码。它是否真的有助于现代机器是有争议的。)

于 2012-07-19T14:01:59.780 回答
2

除了其他人已经提到的评估子表达式的未指定顺序之外,请记住 C++11 添加了线程,这使得执行顺序更加不确定。

例如,如果您有两个线程正在执行,并且每个线程都只打印出“线程 A”或“线程 B”,那么这些输出的生成顺序是完全未指定的。您可能会得到所有“线程 A”输出,然后是所有“线程 B”输出,反之亦然,或者它们可能是任意交错的(更可能是交错)。

于 2012-07-19T15:00:14.520 回答