Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/62.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 何时使用内联函数,何时不使用?_C++_C_Inline - Fatal编程技术网

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

C++ 何时使用内联函数,何时不使用?,c++,c,inline,C++,C,Inline,我知道内联是对编译器的提示或请求,它用于避免函数调用开销 那么,在什么基础上可以确定函数是否是内联的候选函数呢? 在这种情况下,应该避免内联?我通常遵循一个经验法则,在这里我使用3-4条简单语句作为内联语句生成函数。但最好记住,这只是对编译器的一个提示。使其内联或不内联的最后一个调用仅由编译器执行。如果有比这更多的语句,我不会声明内联为一个愚蠢的编译器,它可能会导致代码膨胀 内联函数可以通过消除将参数推入堆栈的需要来提高代码性能。 如果所讨论的函数位于代码的关键部分,则应在项目的优化部分做出内联

我知道内联是对编译器的提示或请求,它用于避免函数调用开销

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

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

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


您可以在

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

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


你可能会感到惊讶,虽然许多C++编译器会自动为你输入小函数,但是他们也可能忽略你的内联请求。

< P>最好的方法是对程序进行配置,标记被调用了很多次的小函数,并通过CPU循环烧毁,如<代码>内联< /代码>。这里的关键字是“small”-一旦函数调用开销与花在函数中的时间相比可以忽略不计,那么内联它们就没有意义了


我建议的另一个用途是,如果您有一些小函数在性能关键代码中被调用的频率足以使缓存丢失相关,那么您可能也应该内联这些函数。同样,探查器应该能够告诉您这一点。

最好的方法是检查和比较生成的内联和非内联指令。但是,忽略
内联
总是安全的。使用
内联
可能会导致您不想遇到的麻烦。

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

做:

  • 使用
    inline
    而不是
    #define
  • 非常小的函数非常适合于
    内联
    :更快的代码和更小的可执行文件(更多的机会留在代码缓存中)
  • 该函数很小,并且经常调用
不要:

  • 大型函数:导致更大的可执行文件,无论调用开销导致的执行速度有多快,都会显著降低性能
  • I/O绑定的内联函数
  • 该函数很少使用
  • 构造函数和析构函数:即使为空,编译器也会为它们生成代码
  • 开发库时破坏二进制兼容性:
    • 内联现有函数
    • 更改内联函数或使内联函数非内联:库的早期版本调用旧实现
在开发库时,为了使类将来可以扩展,您应该:

  • 即使正文为空,也添加非内联虚拟析构函数
  • 使所有构造函数都非内联
  • 编写复制构造函数和赋值运算符的非内联实现,除非不能按值复制该类
请记住,
inline
关键字是对编译器的一个提示:编译器可能决定不内联函数,也可能决定首先内联未标记为
inline
的函数。我通常避免标记函数
内联
(可能在编写非常小的函数时分开)

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

参考资料:

  • 有效C++项目33:使用内联审慎< < /LI>

< >编辑:C++编程语言Bjarne Stroustrup:

函数可以定义为
内联
。例如:

inlineintfac(intn)
{
返回值(n<2)?1:n*fac(n-1);
}
inline
说明符提示编译器,它应该尝试为
fac()
inline的调用生成代码,而不是为函数编写一次代码,然后通过通常的函数调用机制进行调用。聪明的编译器可以为调用fac(6)
生成常量
720
。相互递归的内联函数、递归或不依赖于输入的内联函数等的可能性使得不可能保证
inline
函数的每次调用都是内联的。编译器的聪明程度无法立法,因此一个编译器可能会生成
720
,另一个
6*fac(5)
,还有一个是非内联调用
fac(6)

为了在缺乏异常聪明的编译和链接功能的情况下实现内联,内联函数的定义——而不仅仅是声明——必须在范围内(§9.2)。
inline
specifier不会影响函数的语义。特别是,内联函数仍然具有唯一的地址,因此内联函数的
静态变量(§7.1.2)也是如此

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

函数声明(8.3.5、9.3、11.4),带有
内联inline int fac(int n)
{
  return (n < 2) ? 1 : n * fac(n-1);
}
void IncreaseCount() { freeInstancesCnt++; }
inline bool ValidUser(const std::string& username, const std::string& password)
{
    //here it is quite long function
}