使用关键字inline
来定义,把函数调用处直接进行代码替换。
实际上是否进行代码替换由编译器进行最终决定。此外内联函数被本身所在cpp文件中调用时,才会有如同普通函数一样的地址,具体影响看下面例子。
内联函数的定义问题
1.编译器编译时以cpp为一个编译单元,别的cpp编译完就彻底过去了,对当前编译cpp不造成影响。所以,只有内联函数的定义对编译器编译可见时,才能以代码替换形式实现真正的内联函数。
2.仅在A.cpp定义内联函数,B.cpp声明了该函数,但在B中仍然是不可用,出错的。
在A.cpp和B.cpp中定义一样的内联函数,不会造成重定义。
3.奇异效果:
为减少烦躁心理,以下示例cpp代码中略去#include "stdafx.h"、#include <iostream>、using namespace std;
A.cpp:
inline void m()
{
cout << "A";
}
Main.cpp:
extern void m();
int main()
{
m();
return 0;
}
这样将会报错无法解析的外部符号。
但是,把A.cpp添加修改如下
A.cpp:
inline void m()
{
cout << "A";
}
void ma()
{
m();
}
这样又是可以通过编译的,能正确输出。
前者是编译完后,内联函数没有函数地址,链接时自然找不到。后者新增ma()中调用了m(),使得编译A.cpp时让m有了函数地址(这时编辑器特意拿个特殊小本子记住:这个m()对应这个函数入口地址。不同编译器可能处理不同),连接时m()便是对各cpp可见了。
4.奇异效果x2:
类似A.cpp,写多两个:B.cpp、C.cpp
B.cpp:
inline void m()
{
cout << "B";
}
void mb()
{
m();
}
C.cpp:你懂的。。。
这样仍然能通过编译,编译全部cpp后,函数m()也就有3个函数地址,最后由编译器自行决定留哪一个,丢弃另外两个地址。所以,最后Main.cpp的调用输出可能是"A"、"B"、"C"中的任意一个,ma()、mb()、mc()的结果也是同理。
5.类也是一样的情况
头文件中写类,弄两个cpp分别用inline定义成员函数,然后分别写个函数调用成员函数使得成员函数有入口地址,最后在main函数中调用该成员函数时,最终结果也是编译器自主决定是哪个入口地址的。
6.总结
对于同名函数定义在不同cpp内的情况:
只用inline没有内部调用,其他cpp会外部符号无法解析(找不到定义)。错误!
只用inline且被内部调用,编译器只保留1个函数地址,结果不定但不会重定义。可以!
inline被内部调用后如同普通函数,会与不使用inline定义的普通函数产生重定义冲突。