根据C ++ 03标准1.9 / 5
执行格式良好的程序的符合实现应该产生与具有相同程序和相同输入的抽象机的相应实例的可能执行序列之一相同的可观察行为。
我没有得到“作为其中一个”的部分。
如果我有特定的程序和特定的输入,并且我的程序不包含未定义的行为,为什么可观察的行为会有所不同?在“可能的执行序列之一”下是什么意思?
答案 0 :(得分:12)
在C ++中,某些事情由实现决定。例如,当你写
int x = f(a) + f(b);
实现可以选择先调用f(a)或首先调用f(b)。
答案 1 :(得分:8)
考虑:
x = f() + g();
这允许两个可能的执行顺序:
__temp1 = f(); /*or*/ __temp1 = g();
__temp2 = g(); /*or*/ __temp2 = f();
x = __temp1 + __temp2; /*or*/ x = __temp2 + __temp1;
标准没有规定必须执行哪些;只是该程序必须表现得好像这两个中的一个被执行。如果f()
和g()
有副作用,那么程序可能会有两种不同的可观察行为之一。
答案 2 :(得分:3)
C ++标准没有定义某些表达式的评估顺序。例如,在:
proc( a(), b() );
必须在proc()之前评估a()和b(),但可以在b()之前或之后评估a()。所以有两个合法的执行序列,如果a()和b()有副作用(例如,print语句),你可以知道编译器使用了哪些。
(关于评估顺序的这种自由旨在帮助编译器生成更高效的代码。它是否确实有助于现代机器的争议。)
答案 3 :(得分:2)
除了其他人已经提到的评估子表达式的未指定顺序之外,请记住C ++ 11添加了线程,这使得执行顺序更不确定。
例如,如果您有两个线程正在执行,并且每个线程只打印出“线程A”或“线程B”,则完全不指定生成这些输出的顺序。您可能会获得所有“线程A”输出,然后是所有“线程B”输出,反之亦然,或者它们可能是任意交错的(更可能是交错)。