当 can/will 函数在 C++ 中被内联?可以强制执行内联行为吗?
When can/will a function be inlined in C++? Can inline behavior be forced?
我试图在使用关键字 inline
时获得预期的行为。
我尝试在不同的文件中调用函数、模板化函数、使用内联函数的不同实现,但无论我做什么,编译器都不会内联函数。
那么编译器究竟会在哪种情况下选择内联 C++ 中的函数?
这是我试过的代码:
inline auto Add(int i) -> int {
return i+1;
}
int main() {
Add(1);
return 0;
}
在这种情况下,我得到:
Add(int):
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl , %eax
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
movl , %edi
call Add(int)
movl [=12=], %eax
popq %rbp
ret
或者,
template<typename T>
inline auto Add(const T &i) -> decltype(i+1) {
return i+1;
}
int main() {
Add(1);
return 0;
}
我得到了:
main:
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movl , -4(%rbp)
leaq -4(%rbp), %rax
movq %rax, %rdi
call decltype ({parm#1}+(1)) Add<int>(int const&)
movl [=14=], %eax
leave
ret
decltype ({parm#1}+(1)) Add<int>(int const&):
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl (%rax), %eax
addl , %eax
popq %rbp
ret
我在这里使用 https://gcc.godbolt.org/ 获取汇编代码,但我也在我的机器上尝试了 clang 和 gcc(有和没有优化选项)。
编辑:
好的,我遗漏了一些优化选项。如果我设置 GCC 使用 o3 优化级别,我的方法是 inlined.
但还是。 GCC 或其他编译器如何知道何时最好内联函数?
通常,您的代码 总是 内联,仅当您指定:
__attribute__((always_inline))
例如(来自 gcc 文档):
inline void foo (const char) __attribute__((always_inline));
虽然强制编译器内联代码几乎不是一个好主意。
您可以设置高优化级别(通过 O 标志)以实现最大内联,但有关更多详细信息,请参阅 gcc documentation
内联实际上是由许多参数控制的。您可以使用 -finline-* 选项设置它们。你可以看看他们here
顺便说一句,你实际上并没有声明一个函数。您声明了一个仿函数,一个可以调用但也可以存储状态的对象。而不是使用语法:
内联自动添加(int i)-> int {
你的意思是简单地说:
内联 int Add(int i) {
我试图在使用关键字 inline
时获得预期的行为。
我尝试在不同的文件中调用函数、模板化函数、使用内联函数的不同实现,但无论我做什么,编译器都不会内联函数。
那么编译器究竟会在哪种情况下选择内联 C++ 中的函数?
这是我试过的代码:
inline auto Add(int i) -> int {
return i+1;
}
int main() {
Add(1);
return 0;
}
在这种情况下,我得到:
Add(int):
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl -4(%rbp), %eax
addl , %eax
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
movl , %edi
call Add(int)
movl [=12=], %eax
popq %rbp
ret
或者,
template<typename T>
inline auto Add(const T &i) -> decltype(i+1) {
return i+1;
}
int main() {
Add(1);
return 0;
}
我得到了:
main:
pushq %rbp
movq %rsp, %rbp
subq , %rsp
movl , -4(%rbp)
leaq -4(%rbp), %rax
movq %rax, %rdi
call decltype ({parm#1}+(1)) Add<int>(int const&)
movl [=14=], %eax
leave
ret
decltype ({parm#1}+(1)) Add<int>(int const&):
pushq %rbp
movq %rsp, %rbp
movq %rdi, -8(%rbp)
movq -8(%rbp), %rax
movl (%rax), %eax
addl , %eax
popq %rbp
ret
我在这里使用 https://gcc.godbolt.org/ 获取汇编代码,但我也在我的机器上尝试了 clang 和 gcc(有和没有优化选项)。
编辑:
好的,我遗漏了一些优化选项。如果我设置 GCC 使用 o3 优化级别,我的方法是 inlined.
但还是。 GCC 或其他编译器如何知道何时最好内联函数?
通常,您的代码 总是 内联,仅当您指定:
__attribute__((always_inline))
例如(来自 gcc 文档):
inline void foo (const char) __attribute__((always_inline));
虽然强制编译器内联代码几乎不是一个好主意。
您可以设置高优化级别(通过 O 标志)以实现最大内联,但有关更多详细信息,请参阅 gcc documentation
内联实际上是由许多参数控制的。您可以使用 -finline-* 选项设置它们。你可以看看他们here
顺便说一句,你实际上并没有声明一个函数。您声明了一个仿函数,一个可以调用但也可以存储状态的对象。而不是使用语法:
内联自动添加(int i)-> int {
你的意思是简单地说:
内联 int Add(int i) {