如果我有:
inline int foo(void)
{
return 10 + 3;
}
int main(void)
{
foo();
}
Run Code Online (Sandbox Code Playgroud)
使用GCC,文件编译得很好,但链接器返回 undefined reference to foo
相反,如果我删除inline链接器很高兴!
看起来链接器可以看到外部定义的标识符,但内联定义的标识符不是.
此外,如果我使用-O3标志编译,链接器将看到内联定义的标识符.
有什么问题?
好的,所以在阅读了VivienG的链接之后,我想我已经理解了这个错误信息背后的确切原因.它令人困惑和误导(至少对我来说;如果你只有一个翻译单元就不会发生这种情况),但有可能解释:
假设编译器不想实际内联代码,它必须知道放置该函数的位置,特别是当它在多个转换单元中使用时.
经典的方法是创建多个副本,每个翻译单元一个(或至少对于那些使用它的单位).
这可能会导致问题,例如在尝试进行某些函数指针比较时(尽管如此,仍然会留下问题).
为了解决这个问题(以及我可能没有在这里列出的其他问题),他们认为其中一些实际上非常整洁(尽管 - 如我所说 - 在我看来是误导性的)解决方案:
您可以inline按照您所知的方式声明函数,但同时告诉编译器将非内联版本放在哪里使用extern关键字.
因此,在您的示例中,您将按原样保留函数并将其放在头文件中(因此可以知道它将在何处使用):
inline int foo(void)
{
return 10 + 3;
}
Run Code Online (Sandbox Code Playgroud)
另外,要告诉编译器在哪里放置非内联版本,您必须在一个翻译单元中再添加一个"前向"声明:
extern inline int foo(void);
Run Code Online (Sandbox Code Playgroud)
因此,与经典函数相比,整个概念基本上是相反的:将实现放在标题中,然后在一个文件中进行简短声明.
如前所述,在使用-O3参数时,标记的所有代码inline实际上都是内联的,这不会导致问题发生.