与调用函数相比,goto语句效率高吗?

Are goto statements efficient when compared to calling functions?

本文关键字:语句 效率高 goto 调用 函数      更新时间:2023-10-16

我这里有下面的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;
}

如果我写了一个更大的程序,比如说10000行代码,我决定我永远不会使用我自己写的函数,我只使用goto语句。我只使用全局变量。我在最佳实践方面有点疯狂,但它有一个非常具体的目的。问题是,用goto语句来跳来跳去是否有效?如果我有1000个goto标签呢?

是否goto语句直接翻译成机器码,告诉计算机只是跳转到不同的内存地址?与调用函数的成本相比,像这样在机器中跳来跳去的成本是否更低?

我想知道,因为我想写一个非常高效的程序来做一些计算,我需要非常高效,而不需要诉诸汇编/机器代码。


不必告诉我这在维护、代码的可理解性、最佳实践方面是一个坏主意,我非常清楚,我只是希望有一个问题的答案。我不想争论到底是使用函数调用好还是使用goto好。


为了澄清这个问题,我关心的是,在这种情况下,仅在10,000行程序中使用goto s,它将如何与使用函数的传统程序进行比较。有多种方法可以比较和对比这两个程序,例如CPU缓存如何执行。如果没有函数调用,它会提供什么样的节省?如果没有调用堆栈,这将如何影响CPU缓存,因为CPU缓存通常保持堆栈接近。是否存在这样一种情况,即由于缓存没有被正确利用而可能产生负面的性能影响?调用一个函数的实际代价是什么,与时间效率方面的跳转相比。在效率方面,有很多方法可以比较和对比这两种编程风格。

goto语句直接翻译成机器码,告诉计算机只是跳转到一个不同的内存地址吗?

是的。

与调用函数的成本相比,像这样在机器中跳来跳去的成本更低吗?

是的。

但是,当编译器看到函数调用时,它不必实际生成代码来调用函数。它可以把函数的核心放在调用的地方,甚至不需要跳转。所以调用函数会更有效率!

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

这些只是一些明显的。编译器还可以做很多其他的优化。让编译器来决定。它比你聪明。它比我聪明。编译器知道所有。说真的,克苏鲁可能是个编译器。

你说不要这样做,但我要说:我强烈建议你在决定这样做之前,对配置你的代码,我几乎可以保证这不值得你花时间。编译器(大多数都接近ai级别的智能)可能会生成与常规函数调用一样快或更快的代码,更不用说维护方面了。

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

差不多。

在机器上像这样跳来跳去成本更低吗与调用函数的代价相比?

函数调用将进行非常类似的跳转,但在跳转之前,必须为新函数设置新的堆栈框架,根据调用约定推入参数,最后设置任何返回值并展开。是的,也许不这样做会更快。

我有点疯狂

是的。

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

从您的4个goto标签的小示例中,您来回跳转,不,它在性能方面效率不高。为了避免函数调用机制的开销,这个方法禁用了编译器会自动为您做的许多其他优化。我不列出它们,但这篇文章值得一读。

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

YES(正如其他人正确指出的)

3) 与调用函数的成本相比,像这样在机器中跳来跳去的成本是否更低?

是的,只有当你的编译器是史前的,并且没有任何内置的优化机制。否则没有。

我说的不是最佳实践…

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

当这段代码不能正常工作时,上帝会帮助你的。或者当别人需要维护它的时候。

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

goto语句相当于无条件跳转指令(如JMP)。goto的作用域将在文件内。

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

这些都是课本上的细节。

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

还有很多其他的工具,如循环、条件语句、break和continue语句、函数等,可以帮助你避免这些问题。

希望它能帮助.....

简而言之,'GoTo'语句可能是有效的,但这就是它们的实际使用方式。根据Herbert Schildt ( c++ from the GROUND UP)的说法,"没有任何编程情况需要使用goto语句——它不是使语言完整所必需的项。"最终,许多程序员不喜欢这个语句的主要原因是,goto语句往往会使您的代码混乱,并且/或者使代码很难阅读,因为goto语句可以从一个地方跳到另一个地方。话虽如此,有时候goto语句可以减少混乱并使代码更高效,但这完全取决于您如何使用它们以及使用它们的上下文。就个人而言,我建议使用函数调用,而不是几个goto语句;其他人可能不同意。