是否有任何保证,if-else if-else if-else块的ifs 按照它们的编写顺序进行测试.
我问这是因为我经常试图通过最频繁的情况来首先优化我的代码,我想知道编译器做的一些优化是否会改变测试if的顺序.
所以,如果我正在写这样的代码:
if (cond1) // First if (for the case I have the most often)
{
doSomething1();
}
else if (cond2) // Second if (for the second case I have the most often)
{
doSomething2();
}
else if (cond3) // Third if (for the third case I have the most often)
{
doSomething3();
}
else
{
doElse();
}
Run Code Online (Sandbox Code Playgroud)
是否有任何保证在编译(发布)后,第一个if将被测试,然后是第二个if,然后是第三个if(如果没有条件为真,则最后执行else).
我知道在调试时,ifs按照我编写的顺序执行,但是当程序编译发布时它会保持正常(我主要使用的是g ++和visual studio的最新版本).
此外,由于条件可以对环境产生影响(如if (i=a)或if(myfunction())),它们应该按照书面执行,但我想知道我是否缺少编译器可以执行的某些优化,这会改变ifs的测试顺序.特别是,如果条件没有这样的副作用:
void test(int a)
{
if (a == 1)
{
doSomething1();
}
else if (a == 2)
{
doSomething1();
}
else if (a == 3)
{
doSomething1();
}
else
{
doSomething1();
}
}
Run Code Online (Sandbox Code Playgroud)
是否有任何保证在编译(发布)后,第一个if将被测试,然后是第二个if,然后是第三个if(如果没有条件为真,则最后执行else).
是的,但不是专门用于所有(单线程)代码的if语句.
C++代码从头到尾自上而下执行.唯一可能不是这种情况的情况是,您进行异步调用或让多个线程同时调用相同的代码.
从C++ 03开始,§6.4选择陈述:
1
selection-statement: if ( condition ) statement if ( condition ) statement else statement switch ( condition ) statement[...]如果selection-statement中的子语句是单个语句而不是复合语句,则就好像它被重写为包含原始子语句的复合语句一样.[例:Run Code Online (Sandbox Code Playgroud)if (x) int i;可以等同地重写为
Run Code Online (Sandbox Code Playgroud)if (x) { int i; }[...]
6.4.1
if声明1如果条件(6.4)产生
true第一个子语句,则执行.如果else选择语句的一部分存在且条件产生false,则执行第二个子语句.[...]
从6.4 1开始,您的示例代码相当于:
if (cond1) {
doSomething1();
} else {
if (cond2) {
doSomething2();
} else {
if (cond3) {
doSomething3();
} else {
doElse();
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这并不意味着代码转换为上述代码,而是两者必须表现相同.
从6.4.1,内if时用于外部条件被执行的语句if是false.如果条件是true,则执行第一个分支.虽然标准没有明确说明第二个分支在条件出现时没有执行true,但是遗漏强烈暗示了这一点.
根据§1.91:
本国际标准中的语义描述定义了参数化的非确定性抽象机器.本国际标准对符合实施的结构没有要求.特别是,它们不需要复制或模拟抽象机器的结构.相反,需要符合实现来模拟(仅)抽象机器的可观察行为,如下所述.5)
5)这一规定有时被称为"假设"规则,因为只要结果好像符合要求,只要可以从中确定,实施就可以自由地忽视本国际标准的任何要求.程序的可观察行为.例如,实际实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用,并且没有产生影响程序的可观察行为的副作用.
因此,else如果副作用无效,则可以执行部分子语句,并且即使条件证明结果也会丢弃结果true.例如,如果分支预测错误地预测条件将是,则可以在处理器流水线内部分地执行子语句条件.但是,这种情况的影响必须是不明显的,因此(从您的角度来看),就好像这些子语句的行为符合§6.41和6.4.1 1所述.false
不可以.唯一可以保证的是,可观察的行为"好像"ifs按顺序进行评估.条件的评估甚至可以是交错的,cond2的一部分在cond1之前,而另一部分在cond1之后被评估.另一方面,保证结果将"好像"按顺序评估ifs,如果某些条件有副作用,如果其中一个较早的ifs为真,则不会发生这些副作用.
关于优化,通过一切手段将最可能的条件放在第一位.在实践中,编译器只会在知道运动会改进的情况下移动代码,因此如果条件或多或少独立,并且编译器无法通过折叠部分来"优化"它们,那么将保留顺序.除非编译器特别好,并且可以确定您的排序不是最佳的(基于分析器输出).