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

在C++中,如果需要,内联定义的函数将发出一个函数 在翻译单元之间共享,通常将其放入 需要它的目标文件的公用部分。函数 必须在任何地方都有相同的定义,始终与内联 限定 符。

源 1 和源 2 中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

从每个定义中查找名称可查找相同的实体(之后 过载分辨率(

从这个定义规则 (ODR( 参考:

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

[强调我的]

如果您有 ODR 冲突(由于两个定义不相同,因此您有(,编译器不必发出警告或错误消息。

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

...内联函数:

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 %sn", hanoi(i), hanoi(i) & 1 ? "left" : "right");
}

或者,只是:

hanoi(1);

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

当我:

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

以及无论是否:

  • 传递的参数是即时/文字的
  • 传递的参数是堆栈局部变量
  • 传递的参数是堆分配的静态全局
  • 功能更改为uint32_t f(void) { return 1; }<- 让我感到惊讶!

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

TBH,看起来 VS 在内联功能方面可能有点"脆弱":(

只是我的 2c

\o/-"不要开枪!">

最新更新