简体   繁体   English

为什么在内联 function 中调用的 function 不需要定义?

[英]Why does a function called inside a inline function not require definition?

Consider the following example:考虑以下示例:

extern void not_defined();

void f() {
    not_defined();
}

int main() {}

If I were to compile and link the above program, I get a linker error undefined reference to not_defined() .如果我要编译和链接上面的程序,我会得到一个 linker 错误undefined reference to not_defined() ( https://godbolt.org/z/jPzscK7ja ) ( https://godbolt.org/z/jPzscK7ja )

This is expected because I am ODR using not_defined .这是预料之中的,因为我是使用not_defined的 ODR。

However, if I make f() a inline function, the program compiles and links correctly ( https://godbolt.org/z/qEEob9ann ):但是,如果我将f()设为内联 function,程序将正确编译和链接 ( https://godbolt.org/z/qEEob9ann ):

extern void not_defined();

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

int main() {}

This also works for inline definitions of member functions (since they are also inline?) ( https://godbolt.org/z/xce3neofW ):这也适用于成员函数的内联定义(因为它们也是内联的?)( 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();
}

If I were to uncomment f_free or f_free_inline() in main() it no longer works.如果我在main()中取消f_freef_free_inline()的注释,它将不再有效。 This effects seem to be even transitive, since recurse calls f_member , and f_member calls not_defined() .这种效果似乎甚至可以传递,因为recurse调用f_member ,而f_member调用not_defined()

So my questions is, what's special about inline functions that makes this possible?所以我的问题是,使这成为可能的内联函数有什么特别之处?

EDIT:编辑:

This trick cease to work if the inline function is inside the purview of a module (even if it is not exported):如果内联 function 在模块的范围内(即使它没有被导出),这个技巧将停止工作:

export module mod_interface;

extern void not_defined();

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

The above would result in a linker error for not_defined .以上将导致 not_defined 出现not_defined错误。

This is sad because I am porting a library to modules and suddenly got a lot of undefined references.这很可悲,因为我正在将一个库移植到模块中,突然得到了很多未定义的引用。 Some of those functions in it were wrapped inside inline functions.其中的一些函数被包装在内联函数中。

Standard is not only a set requirements for compiler behaviour.标准不仅仅是对编译器行为的一套要求。 It's also a set of requirements to programmer's behaviour.它也是对程序员行为的一组要求。

GCC's linker wouldn't complain if a function X() that ODR-used a missing symbol Y is inline or static function, as there is no possibility that they would be called from outside module if it has local linkage and negligible, if it was inline.如果 ODR 使用缺失符号Y的 function X()inline的或static function,GCC 的 linker 不会抱怨,因为如果它们具有本地链接并且可以忽略不计,则不可能从外部模块调用它们排队。

But lo, Disregard the fact that you're able to compile and run this program.但是,请忽略您能够编译和运行该程序这一事实。 your program is ill-formed according to standard.根据标准,您的程序格式错误。 Only in case of inline function X() linker would optimize it out as soon as it didn't found a reference to inline X() in any of compile units.只有在 inline function X() linker 的情况下,它才会在没有在任何编译单元中找到对 inline X()的引用时立即优化它。

If it's not inline function, it would stay until final stage of linking and the missing name will be looked up through modules.如果它不是内联的 function,它将一直保留到链接的最后阶段,并且将通过模块查找缺少的名称。 Implementation of your compiler is such that it would be searched for before excluding unused X() .编译器的实现方式是在排除未使用的X()之前搜索它。 Some other compiler may behave differently.其他一些编译器的行为可能不同。

That's why it's "ill-formed" code, but "no diagnostic required".这就是为什么它是“格式错误”的代码,但“不需要诊断”的原因。 Diagnostic is possible with certain implementations.某些实现可以进行诊断。 Some implementations will diagnose both cases as an error and some are unable to detect your deception.有些实现会将这两种情况都诊断为错误,有些则无法检测到您的欺骗行为。 Some implementations will detect the problem only if you had more than one compile unit.有些实现只有在你有多个编译单元时才会检测到问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么通过内联函数进行初始化不需要静态完成 - Why does initialization via inline function is not require to be done statically 为什么 clang 需要在模板中调用函数之前声明它? - Why does clang require a function to be declared before it's called in a template? 为什么通过宏调用的内联错误函数不能返回到main? - Why does this inline error function called through macro not return to main? 为什么编译器在已经具有类资格的成员函数定义的返回类型上要求类限定符? - Why does the compiler require the class qualifier on the return type of an already class-qualified member function definition? C ++:为什么在另一个函数中允许函数声明,但在函数定义中不允许? - C++: Why does function declaration is allowed inside another function but not function definition? 成员函数定义中的内联关键字 - Inline keyword in member function definition 为什么我的 DLL 不需要 DllMain function? - Why does my DLL not require a DllMain function? 为什么内联函数需要传递参数? - Why does an inline function need pass arguments? 函子定义中的函数 - function inside functor definition 为什么这个名为“showTree”的 function 可以正常工作? - Why does this function called: “showTree” work correctly?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM