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

时间:2015-12-10 17:28:47

标签: c++ optimization shared-libraries inline compiler-optimization

根据我的理解,内联函数可以在头文件和源文件中(使用inline关键字),默认情况下,头文件中定义的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中。我的问题是当我们有共享库时,是否需要在头文件中定义内联函数(示例中为add.h),以便使用库的源文件(示例中的main.cpp)获取obj创建本身内联的函数? 在链接时使用-flto没有区别,因为add.o中没有函数?

2 个答案:

答案 0 :(得分:5)

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

如果您在头文件中定义一个函数将其标记为inline,那么#include该标题的每个源文件都会获得该函数的副本,但是您' ve告诉编译器这没关系,链接器也不会抱怨。

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

如果在源文件中定义一个函数并将其标记为inline,则其他源文件中的代码不可见。这就是问题所在:Addadd.cpp中定义,并且标记为inline,因此main.cpp无法看到inline。您可以删除add.cpp或将定义从add.h移至add.h。如果将其移动到inline,您可以将其保留原样并将其放在类定义之后,或者直接在类定义中编写它,而不是将其标记为inline

链接器优化与此完全分开。形式上,inline意味着“如果可以的话,将这个函数扩展到一行”,但编译器通常比你应该做的更好。链接器优化可以内联扩展函数,而不考虑Linq关键字,也不考虑其他文件的可见性。但是代码必须是正确的,所以你必须通过修复代码来解决这个缺失的符号,而不是试图强制进行一些链接器优化。

答案 1 :(得分:2)

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

对这个问题here

有一个很好的答案