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++关键字交互; 我只是在调试时使用它们(当我只想要一个特定的非内联函数在优化后不在内联时)或者在检查生成的代码时(我因为随机内容被内联而感到困惑).
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 解引用的代码的人都知道我在说什么。
[[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 上测试。