在处理指针时,C++编译器能否优化代码?

gab*_*lin 3 c++ optimization pointers

有了这两个问题作为背景(第一第二),我很好奇C++编译器在处理指针时可以执行多少优化?更具体地说,我对编译器在优化它可能检测到的永远不会运行的代码时的智能感兴趣.

(有些人可能会指出,这可能是这个问题的一个骗局,但它的这一特定部分并未得到完全回答.因此我决定开始一个只涉及这个问题的新问题.)

(我不是C++专家,所以我在下面的陈述中可能会出错,但无论如何我都会试一试).C++编译器可以优化掉它将识别的部分代码,它们永远不会被执行或永远不会被退出(例如循环).这是一个例子:


void test() {
    bool escape = false;

    while ( !escape ); // Will never be exited

    // Do something useful after having escaped
}
Run Code Online (Sandbox Code Playgroud)

编译器很可能会认识到循环永远不会被退出,因为代码永远不会改变值,escape以便退出循环.这使得循环无用.

现在,如果我们要将变量更改为指针,编译器是否仍然会优化循环?说代码看起来像这样:


void test( bool* escape ) {
    while ( *escape ); // Will this be executed?

    // Do something useful after having escaped
}
Run Code Online (Sandbox Code Playgroud)

我怀疑编译器取消循环,否则关键字volatile将是多余的,是吗?但是当处理线程时 - 实际上它已被修改但在函数之外,甚至可能在C++文件之外 - 编译器是否仍会删除循环?如果指向的变量escape是全局变量,或者是另一个函数中的局部变量,它会有所不同吗?编译器可以进行此检测吗?在这个问题中,有人说如果在循环内部调用库函数,编译器将不会优化循环.当使用阻止此优化的库函数时,会有什么机制?

Jam*_*ran 9

在第一种情况(while ( !escape );)中,编译器会将其视为label: goto label;并忽略它之后的所有内容(并且可能会给出警告).

在第二种情况(while ( *escape );)中,编译器无法知道*escape在运行时是真还是假,因此它必须执行comaprision和循环.但是请注意,它只需要从*escape读取一次值,即它可以将其视为:

 bool b = *escape;
 label:   if (b) goto label;
Run Code Online (Sandbox Code Playgroud)

volatile 将强制它每次通过循环从'*escape'读取值.