inline 或 constexpr 函数的多个定义的含义

Meaning of multiple definitions for inline or constexpr function

这是我对函数声明和定义的认识。如果有不对的地方还请指正

// Function Declaration
// This is usually put in .h header file
int occur (const char* sentence, const char& achar);

// Function Definition
// This is usually put in .cpp
int occur (const char* sentence, const char& achar) { // do job and return }

我正在阅读 "C++ Primer 5th Edition"。在 "inline and constexpr functions @ Chapter 6.5.2 P.240" 下,显示

Unlike other functions, inline and constexpr functions may be defined multiple times in the program.

我脑子里想出了这样的事情:

// function delcaration .h file
constexpr int returnfour();

// function definition in .cpp file
constexpr int returnfour () { return 4; }
constexpr int returnfour () { return 4; }

像这样定义多个是否正确? defined multiple times in the program 是什么意思,什么时候有人想这样做?

Unlike other functions, inline and constexpr functions may be defined multiple times in the program.

假设你有 a.h:

inline int foo() { return 10; }
constexpr int bar() { return 20; }

现在,您 #include 几个 .cpp 文件中的文件。

file1.cpp:

#include "a.h"

// ... other functions

file2.cpp:

#include "a.h"

// ... other functions

int main() { return 0; }

当您编译这些文件时,函数 foobar 在 file1.cpp 的目标代码以及 file2.cpp 的目标代码中定义。当你 link 那些目标代码创建一个可执行文件时,有两个定义,分别是 foobar。这是合法的。

但是,不允许在同一个编译单元中对同一个inline函数或constexpr函数有多个定义。

使用:

inline int foo() { return 10; }
inline int foo() { return 10; }

constexpr int bar() { return 20; }
constexpr int bar() { return 20; }

在单个 cpp 文件中是不合法的。

函数声明向编译器提供有关函数名称、它接受的参数的数量和类型以及它的 return 值的信息。编译器使用此信息来检查试图调用该函数的语句。

函数定义是一种特定类型的声明,它还包括实现函数的复合语句(函数body的{}之间的部分)。

关于inlineconstexpr函数具有多个定义的声明并不意味着该定义可以在一个编译单元中重复多次。 C++ 有一个单独的编译模型,因此编译器在编译另一个编译单元时看不到一个编译单元中的函数定义。但是,多个编译单元可以分别定义一个 inlineconstexpr 函数(例如,每个 #include 都定义相同的 header)。如果不同的编译单元具有相同函数的 non-equivalent 定义,则结果 - 对于整个程序 - 是未定义的。这样做的结果是 constexprinline 函数的代码可能在程序中重复(例如,在多个地方内联,不是内联而是在 object 文件中以某种方式在本地实现这对其他编译单元等不可见)并且由编译器(通常与构建链的其他部分一起工作)来确保这在编译单元之间以一致的方式发生。

如上所述,inline 和 constexpr 函数可以定义多次。但是它们应该在每个编译单元中只定义一次。通过扩展,如果您在头文件中定义它们并将头文件包含在多个编译单元中,则它们只能在头文件中定义一次。 注意:它们也应该具有相同的签名,否则行为是未定义的。

内联函数和 constexpr 函数都在编译时解析,这就是只要不违反编译单元内的 ODR(一个定义规则)就可以跨编译单元有多个定义的原因.

请参阅C++标准文档的相关摘录:

7.1.5 The constexpr specifier

constexpr functions and constexpr constructors are implicitly inline functions (7.1.2).

3.2 One-definition rule

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program; no diagnostic required. The definition can appear explicitly in the program, it can be found in the standard or a user-defined library, or (when appropriate) it is implicitly defined (see 12.1, 12.4 and 12.8). An inline function shall be defined in every translation unit in which it is odr-used.