共享库的 cpp 文件中的内联函数

Inline functions in cpp files of shared libraries

根据我的理解,内联函数可以进入 headers 以及源文件(使用 inline 关键字)并且默认情况下 headers 中定义的 memeber 函数会被编译器尝试内联。

我的问题是关于以下源文件, add.h

#ifndef ADD_H
#define ADD_H
class Add {
    public:
        int add(int a, int b);
};
#endif  /* ADD_H */

add.cpp

#include <iostream>
#include "add.h"

inline int Add::add(int a, int b) {
    std::cout << "FUNC: " << __func__ << std::endl;
    return a + b;
}

main.cpp

#include "add.h"

int main() {
    Add a;
    a.add(6,7);
    return 0;
}

如果我编译 add.cpp 和 main.cpp

g++ -c add.cpp
g++ -c main.cpp
g++ main.o add.o

它抱怨

main.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `Add::add(int, int)'
collect2: error: ld returned 1 exit status

查看 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

它没有添加函数,我认为这是因为该函数在 .cpp 中是内联的。我的问题是当我们有共享库时,是否需要在 headers(示例中的 add.h)中定义内联函数,以便使用库的源文件(示例中的 main.cpp)获取obj 创建本身内联的功能? 在链接时使用 -flto 没有任何区别,因为 add.o?

中不存在函数

您可以将函数定义放在 header 中。如果它是在 class 定义中定义的,则暗示它是内联的。

这个问题有很好的答案here

如果您在头文件中定义一个函数,#include该头文件的每个源文件都会获得该函数的副本。您会收到链接器的投诉,指出存在重复定义。

如果您在头文件中定义一个函数 并且 标记它 inline,每个 #include 该头文件的源文件都会获得该头文件的副本功能,但你已经告诉编译器那没关系,链接器不会抱怨。

如果您在源文件中定义了一个函数并且没有标记它inline它对其他源文件中的代码可见,因此他们可以调用该函数。

如果您在源文件中定义一个函数并对其进行标记inline,它对其他源文件中的代码不可见。这就是这里的问题:Add 定义在 add.cpp 中,它被标记为 inline,所以它对 main.cpp 不可见。您可以删除 inline 或将定义从 add.cpp 移动到 add.h。如果你把它移动到add.h你可以保持原样放在class定义之后,或者你直接写在class定义里面而不标记它inline .

链接器优化与此完全分开。形式上,inline 表示 "expand this function in line if you can",但编译器通常比您更了解应该做什么。链接器优化可以内联扩展函数,无需考虑 inline 关键字,也无需考虑其他文件的可见性。但是代码一开始就必须是正确的,因此您必须通过修复代码来解决丢失的符号,而不是通过尝试强制进行某些链接器优化。