C++ 在调用者内部扩展被调用者的指导原则是什么(内联-编译器优化)

C++ 在调用者内部扩展被调用者的指导原则是什么(内联-编译器优化),c++,c,caching,inline,compiler-optimization,C++,C,Caching,Inline,Compiler Optimization,我的理解是,编译器遵循某些语义来决定函数是否应该内联扩展。例如,如果被调用方无条件(no if/elelse if to return)返回一个值,则可以在调用方本身中展开该值。类似地,函数调用开销也可以引导这种扩展 类似地,硬件参数(如缓存使用率)也可能在扩展中发挥作用 作为一名程序员,我想了解这些语义和指导内联扩展的算法。最终,我应该能够编写(或识别)肯定是内联(非内联)的代码。我并不是要重写编译器,或者我认为我能够编写比编译器本身更好的代码。问题在于理解编译器的内部结构 编辑:因为我在工作

我的理解是,编译器遵循某些语义来决定函数是否应该内联扩展。例如,如果被调用方无条件(no if/elelse if to return)返回一个值,则可以在调用方本身中展开该值。类似地,函数调用开销也可以引导这种扩展

类似地,硬件参数(如缓存使用率)也可能在扩展中发挥作用


作为一名程序员,我想了解这些语义和指导内联扩展的算法。最终,我应该能够编写(或识别)肯定是内联(非内联)的代码。我并不是要重写编译器,或者我认为我能够编写比编译器本身更好的代码。问题在于理解编译器的内部结构


编辑:因为我在工作中使用了gcc/g++,所以我们可以将范围仅限于这两个方面。不过,我认为在这种情况下,编译器之间会有一些共同点

您不需要理解内联(或其他优化)标准,因为根据定义(假设在这方面没有错误),内联代码的行为应该与非内联代码相同

您的第一个示例(被调用方无条件返回值)实际上肯定是错误的,因为有几个编译器能够内联条件返回

例如,考虑这个代码< F.C.<代码>文件:

static int fact (int n) {
  if (n <= 0) return 1;
  else
    return n * fact (n - 1);
}

int foo () {
  return fact (10);
}
静态整数事实(整数n){

如果(n您不需要理解内联(或其他优化)标准,因为根据定义(假设在这方面没有缺陷),内联代码的行为应该与非内联代码相同

您的第一个示例(被调用方无条件返回值)实际上肯定是错误的,因为有几个编译器能够内联条件返回

例如,考虑这个代码< F.C.<代码>文件:

static int fact (int n) {
  if (n <= 0) return 1;
  else
    return n * fact (n - 1);
}

int foo () {
  return fact (10);
}
静态整数事实(整数n){

如果(n内联就像复制粘贴一样。没有太多的陷阱会阻止它工作,但应该明智地使用它。如果它失去控制,程序将变得臃肿

大多数编译器使用基于“大小”的启发式方法函数的。由于这通常是在任何代码生成过程之前,AST节点的数量可以用作大小的代理。包含内联调用的函数需要将它们包含在自己的大小中,否则内联可能会完全失控。但是,不会生成指令的AST节点不应阻止内联。它可能不同于很难说什么将生成“移动”指令,什么将不生成任何指令

<>因为现代C++倾向于涉及许多没有概念指令的概念重排函数,困难在于区别“没有”指令“只是少数”。移动,以及足够多的移动指令来引起问题。判断特定实例的唯一方法是在调试器中运行程序和/或读取反汇编


主要是在典型的C++代码中,我们假设内联的工作已经足够努力了。对于性能关键的情况,你不能只关注它或者假设任何事情都是最佳工作的。在拆卸级别上的详细的性能分析是必不可少的。

内联就像复制粘贴。没有太多的东西可以阻止它。如果它失去控制,程序将变得臃肿

大多数编译器使用基于“大小”的启发式方法函数的。由于这通常是在任何代码生成过程之前,AST节点的数量可以用作大小的代理。包含内联调用的函数需要将它们包含在自己的大小中,否则内联可能会完全失控。但是,不会生成指令的AST节点不应阻止内联。它可能不同于很难说什么将生成“移动”指令,什么将不生成任何指令

<>因为现代C++倾向于涉及许多没有概念指令的概念重排函数,困难在于区别“没有”指令“只是少数”。移动,以及足够多的移动指令来引起问题。判断特定实例的唯一方法是在调试器中运行程序和/或读取反汇编


主要是在典型C++代码中,我们假设内联工作已经足够努力了。对于性能关键的情况,你不能只关注它或者假设任何事情都是最佳工作的。在拆卸级别上的详细性能分析是必不可少的。

你知道不同的编译器对它的处理方式不同吗?如果函数是虚拟函数,则不要跳过它,有些可能不会。大多数函数进行递归内联,有些则不进行递归内联。问题需要缩小到“特定编译器(示例gcc)如何内联函数”或者其他一些不可能回答的问题。看看:你正在走微观优化的道路,这不是一个好的起点,因为你看不到更大的画面。事实上,你完全错了!@CamelToe:GCC 4.1已经过时,你最好引用最新的GCC文档。。。“最终,我应该能够编写肯定会内联的代码”——你不应该这样做。如果编译器没有内联函数,它有很好的理由(例如保存缓存)。编写总是内联的代码并不能实现最终的性能改进;内联并不是一种神奇的通用性能提升技术。如果你对编译器诚实,不要对它撒谎,让它根据你最初打算编写的代码来做决定,你就能获得最佳的结果。你确实明白不同的编译器处理它的方式不同