代码之家  ›  专栏  ›  技术社区  ›  Ashish

何时使用内联函数,何时不使用?

  •  152
  • Ashish  · 技术社区  · 16 年前

    那么,在什么基础上可以确定函数是否是内联的候选函数呢? 在哪种情况下应该避免内联?

    13 回复  |  直到 12 年前
        1
  •  230
  •   Ian Oakes    16 年前

    避免函数调用的成本只是成功的一半。

    做:

    • 使用 inline 而不是 #define
    • 非常小 内联 :更快的代码和更小的可执行文件(有更多机会留在代码缓存中)
    • 功能很小 经常打电话

    • 大型函数:导致更大的可执行文件,无论调用开销导致的执行速度有多快,都会显著降低性能
    • 该函数很少使用
    • 构造函数和析构函数:即使为空,编译器也会为它们生成代码
    • 开发库时破坏二进制兼容性:
      • 内联现有函数

    在开发库时,为了使类将来可以扩展,您应该:

    • 使所有构造函数都非内联
    • 编写复制构造函数和赋值运算符的非内联实现,除非不能按值复制该类

    内联 关键字是对编译器的提示:编译器可以决定不内联函数,也可以决定内联未标记的函数 内联 内联 (可能在编写非常小的函数时除外)。

    关于性能,明智的方法是(一如既往)评测应用程序,然后最终 内联 表示瓶颈的一组函数。

    参考资料:


    编辑:Bjarne Stroustrup,C++编程语言:

    inline int fac(int n)
    {
      return (n < 2) ? 1 : n * fac(n-1);
    }
    

    内联 说明符是向编译器发出的提示,提示它应该尝试为调用 fac() 内联而不是为函数编写一次代码,然后通过通常的函数调用机制调用。聪明的编译器可以生成常量 720 fac(6) . 相互递归的内联函数、递归或不依赖于输入的内联函数等的可能性使得不可能保证 内联 函数实际上是内联的。一个编译器的聪明程度是无法立法的,因此一个编译器可能会生成 720 另一个 6 * fac(5) ,还有一个是非内联调用 .

    内联 static 内联函数的变量(§7.1.2)。

    编辑2:ISO-IEC 14882-1998,7.1.2功能说明符

    带有 内联 说明符声明一个内联函数。内联说明符向实现表明,在调用点对函数体进行内联替换要优于通常的函数调用机制。在调用点执行此内联替换不需要实现;但是,即使省略了此内联替换,也应遵守7.1.2中定义的内联函数的其他规则。

        2
  •  62
  •   CB Bailey    16 年前

    inline 与优化关系不大。 内联 如果给定的函数定义在程序中多次出现,则编译器不产生错误的指令,并承诺该定义将出现在使用它的每个翻译中,并且无论它出现在何处,都将具有完全相同的定义。

    鉴于上述规则, 内联 适用于短函数,其主体不需要包含声明所需的额外依赖项。每次遇到定义时,都必须对其进行解析,并生成其主体的代码,因此它意味着在单个源文件中只定义一次的函数上会有一些编译器开销。

    编译器可以 内联 (即用执行该函数操作的代码替换对该函数的调用)它选择的任何函数调用。过去的情况是,它“显然”无法内联一个与调用不在同一转换单元中声明的函数,但随着链接时间优化的使用越来越多,即使现在也不是这样。同样正确的是,函数标记为 可能不是内联的。

        3
  •  11
  •   dmazzoni    16 年前

    告诉编译器内联函数是一种优化,最重要的优化规则是过早优化是万恶之源。始终编写清晰的代码(使用高效的算法),然后分析您的程序,只优化耗时过长的函数。

    如果您发现一个特定的函数非常简短,并且在一个紧密的内部循环中被调用了数万次,那么它可能是一个很好的候选者。

        4
  •  5
  •   Timo Geusch    16 年前

    找到答案的最好方法是分析你的程序,标记那些被多次调用的小函数,并将CPU周期消耗殆尽 inline . 这里的关键字是“small”-一旦函数调用开销与花在函数中的时间相比可以忽略不计,那么内联它们就没有意义了。

        5
  •  5
  •   Kornel Kisielewicz    16 年前

    过早优化是万恶之源!

    另一方面,大多数现代编译器都有相当好的优化算法,可以内联您应该内联的内容。

    重新使用——编写内联单行函数,稍后再考虑其他函数。

        6
  •  3
  •   danatel    16 年前

    void IncreaseCount() { freeInstancesCnt++; }
    

    读者立即知道代码的完整语义。

        7
  •  1
  •   wallyk    16 年前

    最好的方法是检查和比较生成的内联和非内联指令。然而,省略总是安全的 inline 可能会给你带来你不想要的麻烦。

        8
  •  1
  •   jball    16 年前

    内联函数 可以 通过消除将参数推入堆栈的需要来提高代码性能。 如果所讨论的函数位于代码的关键部分,则应在项目的优化部分做出内联而非内联决策,

    c++ faq

        9
  •  1
  •   nitish    11 年前

    一个人应该使用 内联

        10
  •  0
  •   Naveen    16 年前

    我通常遵循一条经验法则,在这里我用3-4条简单语句作为内联语句生成一个函数。但最好记住,这只是对编译器的一个提示。使其内联或不内联的最后一个调用仅由编译器执行。如果有比这更多的语句,我不会声明内联为一个愚蠢的编译器,它可能会导致代码膨胀。

        11
  •  0
  •   Rehno Lindeque    16 年前

    在决定是否使用内联时,我通常会记住以下想法:在现代机器上,内存延迟可能是比原始计算更大的瓶颈。通常被调用的内联函数会增加可执行文件的大小。此外,这样的函数可以存储在CPU的代码缓存中,这将减少需要访问代码时缓存未命中的次数。

    我通常在下面列出的情况下使用内联。然而,当您真正关心性能时,分析是必不可少的。此外,您可能需要检查编译器是否真正接受了提示。

    • 非常基本的访问器(get/set)和包装器函数。
    • 像宏一样使用的短代码(例如,最小值()/最大值())
    • 简短的数学程序。
        12
  •  0
  •   Thomas Matthews    16 年前

    inline

        13
  •  0
  •   sachin pathak    6 年前

    当您认为您的代码足够小,可以用作内联函数并记住内联函数时,请复制您的代码并将其粘贴到调用该函数时,这样做可能足以增加执行时间,但也会增加内存消耗。 在使用循环/静态变量/递归/开关/转到/虚拟函数时,不能使用内联函数。 在编译过程中,虚拟方法会一直等到运行时和内联方法,所以它们不能同时使用。

        14
  •  -3
  •   ST3    12 年前

    我读了一些答案,发现有一些东西遗漏了。

    我使用的规则是不使用内联,除非我希望它是内联的。看起来很傻,现在解释一下。

    编译器足够聪明,短函数总是使内联。而且永远不要将长函数作为内联函数,除非程序员要求这样做。

    我知道内联是对编译器的提示或请求

    事实上 inline 是编译器的一个命令,它没有选择和之后 关键字使所有代码内联。所以你永远不能使用 关键字和编译器将设计最短的代码。

    那么什么时候使用呢 内联 ?

    例如,我有以下功能:

    inline bool ValidUser(const std::string& username, const std::string& password)
    {
        //here it is quite long function
    }