Ran*_*olf 1 c++ optimization inline shared-libraries compiler-optimization
根据我的理解,内联函数可以在头文件和源文件中(使用inline关键字),默认情况下,头文件中定义的memeber函数可以由编译器内联.
我的问题是以下源文件add.h
#ifndef ADD_H
#define ADD_H
class Add {
public:
int add(int a, int b);
};
#endif /* ADD_H */
Run Code Online (Sandbox Code Playgroud)
add.cpp
#include <iostream>
#include "add.h"
inline int Add::add(int a, int b) {
std::cout << "FUNC: " << __func__ << std::endl;
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
main.cpp中
#include "add.h"
int main() {
Add a;
a.add(6,7);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我编译add.cpp和main.cpp
g++ -c add.cpp
g++ -c main.cpp
g++ main.o add.o
Run Code Online (Sandbox Code Playgroud)
它抱怨
main.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `Add::add(int, int)'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
看着add.o中的符号,
U __cxa_atexit
U __dso_handle
000000000000003d t _GLOBAL__sub_I_add.cpp
0000000000000000 t __static_initialization_and_destruction_0(int, int)
U std::ios_base::Init::Init()
U std::ios_base::Init::~Init()
0000000000000000 r std::piecewise_construct
0000000000000000 b std::__ioinit
Run Code Online (Sandbox Code Playgroud)
它没有添加函数,我假设是因为函数内联在.cpp中.我的问题是当我们有共享库时,是否需要在头文件中定义内联函数(示例中为add.h),以便使用库的源文件(示例中的main.cpp)获取obj创建本身的内联函数?在链接中使用-flto没有区别,因为add.o中不存在函数?
如果在头文件中定义一个函数,#include那个头的每个源文件都会获得该函数的副本.您将从链接器收到有关重复定义的投诉.
如果你在头文件中定义一个函数并对其进行标记inline,#include那个头的每个源文件都会获得该函数的副本,但是你告诉编译器这没关系,并且链接器不会抱怨.
如果在源文件中定义一个函数而不对其进行标记,那么inline它对其他源文件中的代码是可见的,因此它们可以调用该函数.
如果在源文件中定义一个函数并对其进行标记,inline则对其他源文件中的代码不可见.这就是问题所在:Add定义在add.cpp,并且它被标记inline,因此它是不可见的main.cpp.您可以删除inline或移动定义add.cpp到add.h.如果你将它移动到add.h你可以保持它原样并将它放在类定义之后,或者你直接在类定义中写它而不是标记它inline.
链接器优化与此完全分开.形式上,inline意味着"如果可以的话,将这个功能扩展到行",但编译器通常比你应该做的更好.链接器优化可以内联扩展函数,而不考虑inline关键字而不考虑其他文件的可见性.但是代码必须是正确的,所以你必须通过修复代码来解决这个缺失的符号,而不是试图强制进行一些链接器优化.