c++ - 为什么在内联函数内部调用的函数不需要定义?

标签 c++ inline one-definition-rule

考虑以下示例:

extern void not_defined();

void f() {
    not_defined();
}

int main() {}

如果我编译并链接上述程序,我会收到链接器错误 undefined reference to not_defined() 。 (https://godbolt.org/z/jPzscK7ja)

这是预期的,因为我使用 not_defined 进行 ODR .

但是,如果我做 f()内联函数,程序可以正确编译和链接( https://godbolt.org/z/qEEob9ann ):

extern void not_defined();

// inline is added here
inline void f() {
    not_defined();
}

int main() {}

这也适用于成员函数的内联定义(因为它们也是内联的?)( https://godbolt.org/z/xce3neofW ):

extern void not_defined();

struct C {
    void f_member() { 
        not_defined(); 
    }
    
    void recurse() { 
        f_member(); 
    };
};

inline void f_free_inline() {
    not_defined();
}

// void f_free() {
//     not_defined();
// }

int main() {
    C c;
    // f_free_inline();
}

如果我取消注释f_freef_free_inline()main()它不再起作用了。这种效果似乎甚至是传递性的,因为 recurse来电 f_member ,和f_member来电 not_defined() .

所以我的问题是,内联函数有什么特别之处使得这成为可能?

编辑:

如果内联函数位于模块的权限范围内(即使未导出),则此技巧将不再起作用:

export module mod_interface;

extern void not_defined();

export inline void f_module() {
  not_defined();
}

以上将导致 not_defined 的链接器错误.

这很令人难过,因为我正在将库移植到模块中,突然得到了很多 undefined reference 。其中一些函数被包装在内联函数中。

最佳答案

标准不仅仅是对编译器行为的一组要求。这也是对程序员行为的一套要求。

如果 ODR 使用缺失符号 Y 的函数 X()内联,GCC 的链接器不会提示static 函数,因为如果它具有本地链接并且可以忽略不计(如果它是内联的),则不可能从外部模块调用它们。

但是瞧!不管您是否能够编译并运行该程序,您的程序根据标准都是不正确的。仅在内联函数 X() 的情况下,一旦在任何编译单元中都没有找到对内联 X() 的引用,链接器就会对其进行优化。

如果它不是内联函数,它将保留到链接的最后阶段,并且将通过模块查找缺少的名称。编译器的实现是在排除未使用的 X() 之前对其进行搜索。其他一些编译器的行为可能有所不同。

这就是为什么它是“格式错误”的代码,但“不需要诊断”。通过某些实现方式可以进行诊断。有些实现会将这两种情况诊断为错误,有些则无法检测到您的欺骗。仅当您有多个编译单元时,某些实现才会检测到问题。

关于c++ - 为什么在内联函数内部调用的函数不需要定义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71948111/

相关文章:

c++ - 点集的最大四边形

css - 使用 CSS(内联属性)的内联表单部件?

c++ - (ODR 使用问题)不同文件中同名结构的 priority_queue

c++ - 使用 clang 获取类中的方法列表

c++ - 类成员函数声明疑问

c++ - 访问数据集具有连续名称的 HDF5 文件的最佳方法

c - 如何使用 c 扩展扩展我的 ruby​​ 类?

c - 编译时asm中不可能的约束

c++ - "redefinition"是什么意思?

c++ - 为什么在头文件中定义类不会出现多重定义错误?