type
status
date
slug
summary
tags
category
icon
password
Property
内联函数
C
语言觉得一个小函数重复调用函数栈帧,函数栈帧中保存一些寄存器,之后又销毁,这些都是有消耗的,所以C
语言引入#define宏
:宏的优点:增强代码复用性,提高性能
缺点:
- 不方便调试(预编译阶段进行替换,调试的时候看不到)
- 代码可读性差,维护差,容易误用
- 没有类型的检查(单纯替换不会报错,但是错误)
C++
替代宏的方法:const
修饰的函数(const
成员函数)
- 内联函数
内联函数是
C++
为了改进 C 中类函数宏所作出的努力,内联函数具有闭合子程序的所有特性,然而编译器会将函数调用过程展开为执行代码。优雅地融合了函数和宏的特性。好处在于:更加容易阅读和理解程序意图、行为统一、易于修改和重用,展开执行代码将减轻了函数调用的额外工作:保存寄存器并恢复、赋值参数、程序跳转。由于内联函数将在每一处调用时进行展开,所以,要求要函数将是非常小的,不然生成的执行文件将很大,如果函数是递归的更是不应该内联。而且由于内联展开发生在编译期间,所以,应当将内联函数代码放在头文件中,才能在编译其它文件时进行展开,原因是编译器必须看到执行的代码才能展开。内联函数通常是给编译器的一种提示,编译器会根据实际情况内联或者忽略。
定义内联函数时需要在函数的返回类型前添加关键字
inline
:在函数声明和定义中都能使用关键字
inline
,但是建议只在函数定义时使用。编译时
C++
编译器会在调用内联函数的地方展开,是没有函数压栈的开销的。如果不展开,假设有1000个调用,编译后台就会有10+1000条指令;如果展开,编译后台合计会有 10 * 1000 条指令,这是一场以空间换取时间的交易。因为没有了函数压栈的开销,所以能提高程序运行的效率。
inline
以空间换时间,省去调用函数栈帧开销。适用于优化规模较小、流程直接、调用频繁的函数。所以代码很长、循环或递归的函数不适宜成为内联函数。
- 对于
inline
编译器会自动优化,是否是内联函数不是自己决定的。如果定义为inline
的函数体内有循环/递归等,编译器优化时会忽略掉内联,会被编译为普通函数。
inline
声明和定义不建议分离,分离会导致链接错误。因为inline
被展开,就没有函数地址了,链接就会找不到。
constexpr函数
constexpr
函数指的是在编译的时候就能得到其返回值的函数,也就是说编译器将constexpr
函数直接转换成其返回值,因此,constexpr
函数都是被隐式地定义为内联函数。使用constexpr
关键字来修饰constexpr
函数。constexpr
函数能用于常量表达式的函数。constexpr
函数的返回类型及所有形参的类型都得是字面值类型。另外C++11
标准要求constexpr
函数体中必须有且只有一条 return
语句,但此限制在C++14
中删除。constexpr
函数的返回值可以不是一个常量:当
scale
的实参是常量表达式时,它的返回值也是常量表达式,反之则不然:注:
constexpr
函数不一定返回常量表达式。和其他函数不同,内联函数和
constexpr
函数可以在程序中多次定义。因为在编译过程中,编译器需要函数的定义来随时展开函数,仅有函数的声明是不够的。对于某个给定的内联函数或 constexpr
函数,它的多个定义必须完全一致。因此内联函数和 constexpr
函数通常定义在头文件中。