在 hpp 中声明、在 cpp 中实现并在另一个 cpp 中使用的内联函数的链接错误

Linking error on inline function declared in hpp, implemented in cpp and used in another cpp

当我尝试编译以下项目时出现 linker 错误 undefined reference to function

header.hpp

inline void f(double*, double*, double*);

impl.cpp

inline void f(double* A, double* B, double* C){ ... }

use.cpp

#include "header.hpp"

int main(){
    double *A, *B, *C;
    f(A, B, C);
    return 0;
}

我用g++ -std=c++11 header.hpp impl.cpp use.cpp编译。链接器然后在文件 use.cpp.

中说 undefined reference to f

我注意到如果删除 inline 关键字,一切正常,但我想保留它。

此外,我注意到如果在 use.cpp 中包含 impl.cpp,一切也都正常,但同样,这不是我想要做的,因为我想生成多个二进制文件使用文件 impl.cppimpl2.cpp 等,因此对其中之一进行硬编码也不是办法。

有什么办法可以编译这样的项目link?

The definition of an inline function or variable (since C++17) must be reachable in the translation unit where it is accessed (not necessarily before the point of access).

来源:https://en.cppreference.com/w/cpp/language/inline

use.cpp 无权访问 f 的定义,这就是您收到链接器错误的原因。

为什么要 f 内联?

inline specifier并不是告诉编译器在做优化的时候应该内联这个函数。很久以前就是这种情况,但同时人们意识到编译器在做出这个决定时要好得多:

The original intent of the inline keyword was to serve as an indicator to the optimizer that inline substitution of a function is preferred over function call, that is, instead of executing the function call CPU instruction to transfer control to the function body, a copy of the function body is executed without generating the call. This avoids overhead created by the function call (passing the arguments and retrieving the result) but it may result in a larger executable as the code for the function has to be repeated multiple times.

Since this meaning of the keyword inline is non-binding, compilers are free to use inline substitution for any function that's not marked inline, and are free to generate function calls to any function marked inline. Those optimization choices do not change the rules regarding multiple definitions and shared statics listed above.

如果您想定义内联函数,则需要 inline;)。在您的示例中,inline 将允许您拥有

inline void f(double*, double*, double*) {}

在header。链接器在找到该函数的多个定义时不会抱怨(因为 header 可以包含在多个源中),因为您将其声明为 inline.

the code is meant to be benchmarked and I wanted to prevent the overhead of calling a function

如果消除调用函数的开销是一种可行的优化,编译器将意识到这一点并采取相应行动。