是否可以强制函数不被内联?

Tho*_*son 48 c++ visual-c++

我想强制一个小函数不被编译为内联函数,即使它非常简单.我认为这对于调试目的很有用.有没有关键字可以做到这一点?

Mic*_*kis 50

在Visual Studio 2010中,__declspec(noinline)告诉编译器永远不要内联特定的成员函数,例如:

class X {
     __declspec(noinline) int member_func() {
          return 0; 
     }
};
Run Code Online (Sandbox Code Playgroud)

编辑:此外,在编译时/clr,具有安全属性的函数永远不会被内联(再次,这是VS 2010特有的).

不过,我不认为它在调试时会有用.


小智 44

__declspec(noinline)对于VC++.与手册页相反,这似乎适用于独立功能,我认为我从未将它用于成员函数.你可能 - 虽然注意到我从来没有 - 想要考虑使用优化标志,所以只inline考虑内联函数,虽然这当然具有全局效果,可能不是你想要的.

__attribute__((noinline))for gcc(以及一些支持gcc属性语法的不太常用的编译器).我必须承认,我认为我从来没有真正使用过它,但它似乎就在那里.

(当然,这两种注释样式会在不同的地方出现,因此构造对两者都很合适的代码有点烦人.)

我不确定这些中的任何一个如何与inlineC++关键字交互; 我只是在调试时使用它们(当我只想要一个特定的非内联函数在优化后不在内联时)或者在检查生成的代码时(我因为随机内容被内联而感到困惑).

  • 它也适用于成员函数。一个有趣的注意事项是,它似乎也会对包含的函数进行非内联调用(即使它们会内联) - VS 2012 (2认同)

Mot*_*tti 13

请记住内联在函数调用站点是相关的,在某些情况下可以内联相同的函数而在其他情况下不内联.

如果您的函数在编译单元外部可见,那么即使它在所有当前使用的位置内联,函数体也必须仍然可供以后想要调用它的任何人使用(通过链接目标文件).

为了使调用站点不内联,您可以使用指向函数的指针.

void (*f_ptr)(int); // pointer to function
volatile bool useMe = true; // disallow optimizations 
if (useMe)
   f_ptr = myFunc;
else
   f_ptr = useOtherFunc;

f_ptr(42); // this will not be inlined
Run Code Online (Sandbox Code Playgroud)


小智 5

简单:不要让编译器看到函数的定义。那么它不可能被内联。当然,这仅适用于您的代码。

在调试 3rd 方代码时……是的,这很有用,特别是如果您可以从远处扫 3rd 方代码。任何调试过包含大量 shared_ptr 解引用的代码的人都知道我在说什么。


Cir*_*四事件 5

[[gnu::noinline]] 属性

我们还可以将 C++11 属性说明符语法与非标准gnu::noinline属性一起使用:https : //en.cppreference.com/w/cpp/language/attributes

gnu::部分被丢弃未来的 C++ 标准以提供标准化只是时间问题[[noinline]]:-)

主程序

[[gnu::noinline]]
int my_func() {
    return 1;
}

int main() {
    return my_func();
}
Run Code Online (Sandbox Code Playgroud)

编译和反汇编:

g++ -ggdb3 -O3 -o main.out -std=c++11 -Wall -Wextra -pedantic-errors main.cpp
gdb -batch -ex 'disassemble/r main' main.out
Run Code Online (Sandbox Code Playgroud)

[[gnu::noinline]]

   0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     e9 f7 00 00 00  jmpq   0x1140 <my_func()>

Run Code Online (Sandbox Code Playgroud)

没有[[gnu::noinline]]

   0x0000000000001040 <+0>:     f3 0f 1e fa     endbr64 
   0x0000000000001044 <+4>:     b8 01 00 00 00  mov    $0x1,%eax
   0x0000000000001049 <+9>:     c3      retq
Run Code Online (Sandbox Code Playgroud)

在 Ubuntu 19.10 上测试。