7

我在这里有以下 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 标签怎么办?

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

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


无需告诉我,就维护、代码的可理解性、最佳实践而言,这是一个坏主意,我非常清楚这一点,我只想回答这个问题。我不想在函数调用好用还是 goto 好用之间争论。


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

4

6 回答 6

29

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

是的。

与调用函数的成本相比,这样在机器中跳转的成本是否更低?

是的。

但是,当编译器看到函数调用时,它不必实际生成代码来调用函数。它可以利用函数的核心并将它们固定在调用所在的位置,甚至不会跳转。所以调用函数可能更有效!

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

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

你说不要,但我要说:我强烈建议你在决定这样做之前分析你的代码,我几乎可以保证这不值得你花时间。编译器(其中大部分是接近 AI 级别的智能)可能可以通过常规函数调用生成更快或更快的代码,更不用说维护方面了。

于 2013-01-07T05:22:29.713 回答
16

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

差不多。

与调用函数的成本相比,这样在机器中跳转的成本是否更低?

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

我有点疯狂

是的。

于 2013-01-07T05:21:53.850 回答
4

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

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

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

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

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

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

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

于 2013-01-07T05:58:49.263 回答
3

是的,从 goto 生成的机器代码将是一个直接的 JUMP。这可能会比函数调用更快,因为不需要对堆栈做任何事情(尽管没有任何要传递的变量的调用将被优化为可能同样快)。

当此代码无法正常工作时,上帝会帮助您。或者当其他人必须维护它时。

于 2013-01-07T05:23:43.210 回答
2

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

goto 语句等效于无条件跳转指令(例如 jmp )。goto 的范围将在文件内。

Ritchie 建议避免使用 goto 语句,如果仍然想/必须使用 goto 语句,则使用自顶向下的方法,不要使用自底向上的方法。

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

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

还有许多其他工具,例如循环、条件语句、break 和 continue 语句、函数等,可以帮助您避免此类问题。

希望能帮助到你.....

于 2013-01-07T05:34:33.200 回答
0

简而言之,'GoTo' 语句可能很有效,但这就是它们的实际使用方式。根据 Herbert Schildt 的说法(来自 GROUND UP 的 C++), “没有需要使用 goto 语句的编程情况——它不是使语言完整所必需的项目。” 归根结底,许多程序员不喜欢该语句的主要原因是 goto 语句往往会使您的代码混乱和/或使其非常难以阅读,因为根据名称,goto 可以从一个地方跳到另一个地方。话虽如此,有时 goto 语句可以减少混乱并提高代码效率,但这完全取决于您如何使用它们以及使用它们的上下文。就个人而言,我建议使用函数调用,与几个 goto 语句相反;其他人可能不同意。

于 2013-01-07T05:25:04.570 回答