1

关于这个命令有很多争论goto,这个问题不是关于它使用的对错,而是更简单的问题是它是否真的创建了不同的程序集。

我特别关注 Visual Studio 2013,但任何编译器中的示例都会很棒。

Bjarne Stroustrup 说

标签的范围是它所在的功能(第 6.3.4 节)。这意味着您可以使用goto跳进和跳出块。唯一的限制是您不能跳过初始化程序或异常处理程序(第 13.5 节)。
在普通代码中为数不多的合理用途之一goto是从嵌套循环或switch语句中跳出。

那么我的问题是:是否有任何实例goto仍然会产生与使用其他控制结构已经可以完成的程序不同的程序集?

例如,这会产生相同的程序集:

auto r = rand();
auto a = 0;

for(auto i = rand(); i > 0; --i){
    switch(r){
    case 1:
        ++sum;
        goto END;
    case default:
        sum += rand();
        break;
    }
}
sum++;
END:

对于这个非goto代码:

auto r = rand();
auto b = false;
auto a = 0;

for(auto i = rand(); i > 0; --i){
    switch(r){
    case 1:
        ++sum;
        b = true;
        break;
    case default:
        sum += rand();
        break;
    }
    if(b)break;
}

if(!b)sum++;
4

1 回答 1

1

这是我的经验:我曾经有过一些对时间非常关键的代码。它有一个平均迭代零次的循环(while (condition) ...)并且条件几乎总是错误的。编译器坚持循环优化,将事物移到循环之外——即使循环根本没有执行,因此减慢了它的速度。

我尝试使用 goto 重写循环,希望能将优化器混淆到足以放弃优化代码,但失败了。gcc 和 clang 优化取决于实际的控制流,而不是取决于你使用什么 C 或 C++ 代码。

于 2015-06-02T16:32:38.883 回答