C++的inline函数看似简单,却是非常容易出问题的地方。需要特别小心,不小心可能会被遇到的错误吓到。C++的版本虽然不断修订,inline函数的缺陷却一直没有被人注意到。
来看下面的例子,这里分3个文件,一个x.h头文件,一个x.cpp实现class math中的成员函数代码,一个main.cpp实现主程序代码:
//x.h
class math{
double x;
inline double expimp(int n);
public:
math(double x):x(x){}
double exp(int n) {return expimp(n);}
};
//x.cpp
#include "x.h"
inline double math::expimp(int n)
{
int i;
double s=1.0;
for(i=1; i<n; i++) {
s *= x;
}
return s;
}
double also(math m)
{
return m.exp(3);
}
//main.cpp
#include <stdio.h>
#include "x.h"
inline double math::expimp(int n)
{
printf("using inline func %s(not imp)\n", __FUNCTION__);
return 1.09;
}
extern double also(math m);
int main()
{
math m(1.1);
double x = m.exp(3);
printf("x=%lf\n", x);
x = also(m);
printf("x=%lf\n", x);
return 0;
}
这里x.cpp和main.cpp的代码中都出现了expimp函数的一个inline实现。
下面是用g++编译的运行结果:
1。用 g++ main.cpp x.cpp -o x 编译,结果用了main.cpp中的实现:
using inline func expimp(not imp)
x=1.090000
using inline func expimp(not imp)
x=1.090000
2。用g++ x.cpp main.cpp -o x 编译,结果用了x.cpp中的实现:
x=1.210000
x=1.210000
3。用-O2优化编译,g++ -O2 main.cpp x.cpp -o x,结果一个用了main.cpp中的版本, 一个用了x.cpp中的版本:
using inline func expimp(not imp)
x=1.090000
x=1.210000
同样的代码,编译的结果跟编译的顺序,有没有优化有关。虽然可以把inline函数统一放在头文件里。这样可以保证只有一份源代码。但是受条件编译的影响,编译出来的目标代码可能并不一样。当偶然的,把release版本的obj和debug版本的obj link到一起时,可能会出现意想不到的问题。