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

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

推荐答案

避免函数调用的成本只是故事的一半.

执行以下操作:

  • 使用inline而不是#define
  • very small个函数很适合inline个:更快的代码和更小的可执行文件(更多的机会留在代码缓存中)
  • 这个函数很小,经常调用

不要:

  • 大型函数:导致更大的可执行文件,这会显著降低性能,而不管调用开销导致的执行速度有多快
  • 受I/O限制的内联函数
  • 这个功能很少使用
  • 构造函数和析构函数:即使是空的,编译器也会为它们生成代码
  • 开发库时 destruct 二进制兼容性:

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

  • 添加非内联虚拟析构函数,即使正文为空
  • 使所有构造函数都非内联
  • 编写复制构造函数和赋值运算符的非内联实现,除非不能按值复制该类

请记住,关键字inline是对编译器的一个提示:编译器可以决定不内联函数,并且可以决定内联最初没有标记为inline的函数.我通常避免标记函数inline(可能在编写非常非常小的函数时分开).

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

参考资料:


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

一个函数可以定义为inline.例如:

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

inline说明符是对编译器的一个提示,它应该try 为内联调用fac()生成代码,而不是只放置函数的代码一次,然后通过通常的函数调用机制进行调用.聪明的编译器可以为调用fac(6)生成常量720.相互递归的内联函数、依赖于输入的递归或不递归的内联函数等的可能性使得不可能保证inline函数的每个调用实际上都是内联的.编译器的聪明程度不能被立法,因此一个编译器可能生成720,另一个生成6 * fac(5),而另一个生成未内联调用fac(6).

为了在没有异常聪明的编译和链接功能的情况下实现内联,内联函数的定义——而不仅仅是声明——必须在范围内(§9.2).inline介词不影响函数的语义.特别是,内联函数仍然有一个唯一的地址,因此内联函数有static个变量(§7.1.2).

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

带有inline说明符的函数声明(8.3.5、9.3、11.4)声明一个内联函数.内联说明符向实现表明,在调用点对函数体进行内联替换比通常的函数调用机制更可取.在调用点执行这种内联替换不需要实现;然而,即使省略了这种内联替换,也应遵守7.1.2中定义的内联函数的其他规则.

C++相关问答推荐

ARM上的Modulo Sim Aarch 64(NEON)

为什么在C中设置文件的位置并写入文件,填充空字符?

将 typewriter LF打印到Windows终端,而不是隐含的CR+LF

为什么在4.9.37版的内核中,kfio还需要smp_wmb呢?

如何使fputs功能提示错误输入并要求用户重新输入.程序停止而不是请求新的输入

我可以在C中声明不同长度数组的数组而不带变量名吗?

C中函数类型的前向声明

从uint8_t*转换为char*可接受

OpenSSL:如何将吊销列表与SSL_CTX_LOAD_VERIFY_LOCATIONS一起使用?

在编写代码时,Clion比vscode有更多的问题指示器

C整型和_泛型.哪些类型是兼容的?

Printf()在C中打印终止字符之后的字符,我该如何解决这个问题?

CS50判断灯泡运动的问题,判断时多出一个灯泡,但不在终端上

为什么编译器不能简单地将数据从EDI转移到EAX?

条件跳转或移动取决于未初始化值(S)/未初始化值由堆分配创建(Realloc)

C:Assignment中的链表赋值从指针目标类型中丢弃‘const’限定符

被调用方函数内部的C-Struct变量,它是指针还是无关紧要

将数组中的所有元素初始化为 struct 中的相同值

std::malloc/calloc/realloc/free 与纯 C 的 malloc/calloc/realloc/free 有什么不同

使用共享变量同步多线程 C 中的函数