添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

引子程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// file.cc
inline void foo(void)
{
/*函数体*/
}

// file.h
void foo(void);

// main.cc
int main()
{
foo();
}

上面的编码会出现什么问题? 链接错误,显示foo未定义(undefined reference to `foo()’).

编译器对inline函数的处理

使用inline函数,意图是在函数调用处直接替换成函数体,省去函数调用,提高函数的执行效率.但编译器在处理的时候,真正的处理流程是什么样的呢?

我们知道,c/c++程序编译分为几个阶段,预处理->编译+汇编->链接. inline的处理阶段发生在编译阶段. 也就是说,在编译阶段完成后,目标模块的inline函数要么被替换了,要么没有被替换,但是链接时可以找到inline函数的定义.也就是说,在编译阶段之前,目标模块需要看到inline函数的实现.

拿引子程序来说,编译main.o目标模块时,编译器”看到”了foo的声明,此时它并不知道foo是要inline的.编译file.o目标模块时,编译器看到foo的实现,并且声明为inline,由于foo在file.o没有被使用到,所以,inline函数不被保留.链接的时候,当然也就找不到foo的定义实体了.针对此例子,我们可以在file.c定义一处函数,使用了一次foo(),编译就可以通过.

1
2
3
4
5
//file.cc
int foo2()
{
foo();
}

正确的做法是,inline函数的实现(定义)要跟随其函数声明放在.h文件中.编译器在编译阶段就可以看见函数实现,从而进行替换.(这一点有点向函数模板,函数模板也是要放在声明文件中,不能单独放在源文件中)

inline和宏的区别