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

标签 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 标签怎么办?

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

我想知道,因为我想编写一个非常高效的程序来进行一些计算,我需要在不借助汇编/机器代码的情况下非常高效。


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


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

最佳答案

Do the goto statements translate directly into machine code which tells the computer just to JUMP to a different memory address?

是的。

Is this a lower cost in the machine to jump around like this when compared with the cost to call a function?

是的。

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

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

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

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

关于c++ - 与调用函数相比,goto 语句是否有效?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14190274/

相关文章:

c++ - 增加元组类型的 hana 大小

c++ - Qt - 在其他线程上运行函数

assembly - 修改了 C64 PRG BASIC header ?

c - 使用 gcc 编译时,函数和变量会以 "_"开头吗?

objective-c - 使用未声明的标识符 '_bridge'

assembly - x86_32 虚拟 8086 和实模式是否支持扩展通用和专用寄存器?

assembly - 如何使用 1 寻址模式通过在汇编中加载来添加两个存储值?

c++ - 如何将一个对象的引用传递给另一个对象并仍然修改第一个对象?

c++ - C++ 中的委托(delegate)(或类似的东西)

铿锵错误: linker command failed with exit code 1104