【问题标题】:Meaning of multiple definitions for inline or constexpr functioninline 或 constexpr 函数的多个定义的含义
【发布时间】:2016-01-17 05:27:29
【问题描述】:

这是我对函数声明和定义的了解。如有不妥,请指正。

// 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”下,它说

与其他函数不同,可以定义 inline 和 constexpr 函数 在程序中多次。

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

// 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 是什么意思,什么时候有人想这样做?

【问题讨论】:

    标签: c++ function declaration definition


    【解决方案1】:

    与其他函数不同,inlineconstexpr 函数可以在程序中定义多次。

    假设你有 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 的目标代码中定义。当您链接这些目标代码以创建可执行文件时,foobar 各有两个定义。这是合法的。

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

    使用:

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

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

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

    【讨论】:

    • 我选择接受这个答案,因为它通过易于理解的示例进行说明。
    【解决方案2】:

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

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

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

    【讨论】:

      【解决方案3】:

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

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

      请参阅C++标准文档的相关节选:

      7.1.5 constexpr 说明符

      constexpr 函数和 constexpr 构造函数是隐式的 内联函数 (7.1.2)。

      3.2 一定义规则

      每个程序都应该包含一个对每个非内联函数或 odr 使用的变量的定义 在该计划中;无需诊断。定义可以显式出现在程序中,可以查到 在标准库或用户定义库中,或(在适当时)隐式定义(参见 12.1、12.4 和 12.8)。内联函数应在使用它的每个翻译单元中定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-04-19
        • 2020-04-18
        • 2020-07-29
        • 1970-01-01
        • 2014-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多