VS2019中内联函数的一些问题

时间:2019-12-09 08:30:40

标签: c++ visual-studio language-lawyer inline msvc14

我正在做一些关于VS2019中C ++内联函数的实验(也许是外来的):

source1:

#include "pch.h"

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

void testinline1()
{
    inline_func(0);
}

source2:

#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的“内联函数的存储类”部分,

  

在C ++中,如果需要,内联定义的函数将发出一个函数   在翻译单位之间共享,通常是将其放入   目标文件所需的公共部分。功能   在任何地方都必须具有相同的定义,并且总是内联   限定词。

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

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

为什么会这样?这是C ++不能覆盖的地方,还是MSVC不能覆盖的地方吗?

回答后更新

这是一个更好的例子:

source1:

#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();
}

source2:

#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

  在每个定义中的

名称查找会找到相同的实体(   超载分辨率)

2 个答案:

答案 0 :(得分:4)

来自this One Definition Rule (ODR) reference

  

如果满足所有这些要求,则程序的行为就好像整个程序中只有一个定义。否则,程序格式错误,无需诊断

[重点突出]

如果您有违反ODR的行为(由于两个定义不相同,您就有此行为),则编译器不必发出警告或错误消息。

答案 1 :(得分:0)

有趣的是,在 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" ://p>

和我一样:

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

并且不管是否:

  • 传递的参数是直接/文字
  • 传入的参数是栈局部变量
  • 传递的参数是堆分配的静态全局
  • 函数改为uint32_t f(void) { return 1; } <--让我吃惊!

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

TBH,当涉及到内联函数时,VS 看起来可能有点“脆弱”:(

只是我的 2c

\o/ - “不要开枪!”