VS2019 内联函数的一些问题

Some problem about inline function in VS2019

我正在 VS2019 中做一些关于 C++ 内联函数的(可能是奇特的)实验:

来源 1:

#include "pch.h"

inline int inline_func(int i) {
    return  i;
}

void testinline1()
{
    inline_func(0);
}

来源 2:

#include "pch.h"

inline int inline_func(int i) {
    return  i*i ;
}

void testinline2()
{
    inline_func(0);
}

主要来源:

#include "pch.h"

inline int inline_func(int i);
int main(int argc,char* argv[])
{   
    int i = inline_func(2);
}

根据 http://en.wikipedia.org/wiki/Inline_function 的 "Storage classes of inline functions" 部分,

In C++, a function defined inline will, if required, emit a function shared among translation units, typically by putting it into the common section of the object file for which it is needed. The function must have the same definition everywhere, always with the inline qualifier.

source1和source2中inline_func的定义不同所以应该有错误,但是在VS2019中没有这样的错误。

main() 中 i 的结果是 2,它来自 source1 中的 inline_func,这似乎是构建过程的随机选择,因为如果我在 source1 中注释 testinline1,那么我将成为4 因为 source1 中的 inline_func 不会出现在目标文件中,除非在同一源中使用。当我在 source2 中评论 testinline2 时,inline_func 也会出现未定义的符号错误。

为什么会发生这些?这是 C++ 没有涵盖的地方还是只有 MSVC 没有涵盖的地方?

回答后更新:

这是一个更好的例子:

来源 1:

#include "pch.h"

int non_inline_func();
inline int inline_func2() {
    return  non_inline_func();
}

static int non_inline_func()
{
    return 1;
}

int public_func1() 
{
    return inline_func2();
}

来源 2:

#include "pch.h"

int non_inline_func();
inline int inline_func2() {
    return  non_inline_func();
}

static int non_inline_func()
{
    return 2;
}

int public_func2()
{
    return inline_func2();
}

主要来源:

#include "pch.h"

int public_func1();
int public_func2();

void TestInline()
{
    int i =public_func1();
    int j= public_func2();
}

结果是i=j=1。内联函数的定义在这里是一样的。这应该违反:https://en.cppreference.com/w/cpp/language/definition#One_Definition_Rule

name lookup from within each definition finds the same entities (after overload-resolution)

来自this One Definition Rule (ODR) reference

If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the program is ill-formed, no diagnostic required.

[强调我的]

如果您有 ODR 违规(因为这两个定义不相同),编译器不必发出警告或错误消息。

有趣的是,在 MSVS2019 ISO C++ 14 中...

内联函数:

inline uint32_t hanoi(int a) { __asm  bsf eax, a } // Solve arbitrary 'Tower of Hanoi' round

通过以下任一方式调用:

int numMoves = (1<<numDisks)-1; /* Calculate number of moves needed to solve */

// Print full Tower Of Hanoi solution
for (int i = 1;i < numMoves;i++) {
    printf("move disk %u %s\n", hanoi(i), hanoi(i) & 1 ? "left" : "right");
}

或者,只是:

hanoi(1);

不内联。它总是导致编译器发出 "Call" :/

我也一样:

  • 使用 std::cout ... 像个好孩子; )
  • 直接调用函数(丢弃)或;
  • 直接调用函数(利用return值)

并且不管是否:

  • 传递的参数是immediate/literal
  • 传递的参数是栈局部变量
  • 传递的参数是堆分配的静态全局
  • 函数更改为 uint32_t f(void) { return 1; } <-- 令我惊讶!

我注意到有人比我更聪明地抱怨 VS2015 和 VS2017 中的类似 in-lining 问题 - 每个人都将其与 CLANG 和 GCC 中的相同代码进行比较,后者的编译器似乎没有任何问题: / 每次 MS 似乎都将其确定为编译器问题。

TBH,看起来 VS 在 in-lining 函数方面可能只是有点 'fragile' :(

只是我的 2c

\o/ - “别拍!”