与调用函数相比,goto语句是否有效?

时间:2013-01-07 05:16:01

标签: c++ c assembly goto machine-code

我在C ++中有以下代码:

#include <iostream>

int main(int argc, const char * argv[])
{
    goto line2;
line1:
    std::cout << "line 1";
    goto line3;
line2:
    std::cout << "line 2";
    goto line1;
line3:
    std::cout << "line 3";
    goto line4;
line4:
    std::cout << "Hello, World!\n";
    return 0;
}

如果我制作了一个更大的程序,让我说10,000行代码,我决定永远不会使用我自己编写的函数,我只使用goto语句。我只使用全局变量。就最佳实践而言,我有点疯狂,但它的用途非常特殊。问题是,使用goto语句跳转是否有效?如果我有1000个转到标签怎么办?

goto语句是否直接转换为机器代码,告诉计算机JUMP只是一个不同的内存地址?与调用函数的成本相比,机器中的这种成本是否会降低?

我希望知道,因为我想编写一个非常有效的程序来进行一些计算,我需要非常高效,而不需要求助于汇编/机器代码。


无需告诉我这在维护,代码的可理解性,最佳实践方面都是一个坏主意,我非常清楚这一点,我只想回答这个问题。我不想在它是否善于使用函数调用或使用goto之间进行任何争论。


为了澄清这个问题,我担心在这种情况下只使用带有10,000行程序的gotos,它将如何与使用函数的传统程序进行比较。有两种方法可以比较和对比这两个程序,例如CPU缓存的执行方式。没有函数调用它会给出什么样的保存。如果没有调用堆栈,这将如何影响CPU缓存,因为CPU缓存通常会使堆栈保持关闭状态。是否会出现由于未正确使用缓存而导致性能损失的情况。与时间效率方面的跳跃相比,调用函数的实际成本是多少。在效率方面,有很多方法可以比较和对比两种编程风格。

6 个答案:

答案 0 :(得分:22)

  

goto语句是否直接转换为机器代码,告诉计算机JUMP只是一个不同的内存地址?

  

与调用功能的成本相比,机器中的这种成本是否会降低?

但是,当编译器看到函数调用时,它不必实际生成调用函数的代码。它可以采取功能的内容,并将它们粘在呼叫所在的位置,甚至不是跳跃。因此调用函数可能更有效!

此外,代码越小,效率越高(一般来说),因为它更有可能适合CPU缓存。编译器可以看到这一点,并且可以确定函数何时很小并且最好内联它,或者当它很大并且更好地将它分离并使其成为真正的函数时,生成最快的代码(如果你将它设置为生成)最快的代码)。你看不到这个,所以你猜错了,可能猜错了。

这些只是一些显而易见的问题。编译器可以做很多其他优化。让编译器决定。它比你聪明。它比我聪明。 编译器知道所有。说真的,Cthulhu可能是编译器。

你说没有,但我会说:我强烈建议你描述你的代码,然后再决定这样做,我几乎可以保证你不值得花时间。编译器(大多数是近AI级智能)可能会生成快速或更快的代码与常规函数调用,更不用说维护方面了。

答案 1 :(得分:13)

  

goto语句是否直接转换为机器代码   告诉计算机只是JUMP到一个不同的内存地址?

差不多。

  

这是一个较低的成本,机器跳这样的时候   与调用函数的成本相比?

函数调用将进行非常相似的跳转,但在进行跳转之前,必须为新函数设置新的堆栈帧,根据调用约定推送参数,并在结束时设置任何返回值和放松。是的,不这样做可能会更快。

  

我有点疯了

答案 2 :(得分:3)

是的,从goto生成的机器代码将是一个直接的JUMP。这可能比函数调用更快,因为没有必要对堆栈进行任何操作(尽管没有任何变量传递的调用将以可能同样快的方式进行优化)。

当某些内容无法使用此代码时,上帝会帮助你。或者当其他人必须维护它时。

答案 3 :(得分:3)

  

1)问题是,使用goto语句跳转是否有效?如果我有1000个转到标签怎么办?

从包含4个goto标签的小例子中,您可以来回来回,但就性能而言,效率并不高。为避免函数调用机制的开销,此方法禁用编译器将自动为您执行的许多其他优化。我没有列出它们,但this值得一读。

  

2) goto语句是否直接转换为机器代码,告诉计算机JUMP到另一个内存地址?

是(正如其他人正确指出的那样)

  

3)与调用函数的成本相比,机器中的这种成本是否更低?

是,仅当您的编译器是历史记录时,并且没有构建任何优化机制。否则没有。

我不是在谈论最佳实践..

答案 4 :(得分:1)

很难准确回答您的查询,这取决于您的程序的复杂性和使用goto语句。

goto语句相当于无条件跳转指令(例如jmp)。 goto的范围将在文件中。

Ritchie建议避免使用goto语句,如果仍然想要/必须使用goto语句,那么在自上而下的方法中使用它,不要在自下而上的方法中使用它。

这些是教科书的详细信息。

实际上你应该非常确定在哪里使用goto语句并在goto跳转到你的程序流程之后,否则正如你提到的1000 goto语句那样你也很难决定程序流程,忘记其他人。因此,进一步改进您的计划将非常困难。

还有很多其他功能,例如循环,条件语句,中断和继续语句,函数等,可以帮助您避免此类问题。

希望它有所帮助.....

答案 5 :(得分:0)

简而言之,“GoTo”语句可以很有效,但这确实是它们的使用方式。根据Herbert Schildt( C ++来自GROUND UP ),“没有编程情况需要使用goto语句 - 它不是使语言完整所必需的项目。”最终,许多程序员不喜欢这种说法的主要原因是goto语句往往会使你的代码混乱和/或使其难以阅读,因为根据名称,gotos可以从一个地方跳到另一个地方。有了这样的说法,有时候goto语句可以减少混乱并使代码更有效,但这完全取决于你如何使用它们以及它们所使用的上下文。就个人而言,我建议使用函数调用,反对几个goto声明;其他人可能不同意。