这个问题听起来太简单了,不能在某个地方得到回答,但我试着环顾四周,找不到任何简单的答案。下面是一个例子:
class vec
{
double x;
double y;
};
inline void sum_x(vec & result, vec & a, vec & b)
{
result.x = a.x + b.x;
}
inline void sum(vec & result, vec & a, vec & b)
{
sum_x(result, a, b);
result.y = a.y + b.y;
}当我调用sum并编译时会发生什么?sum和sum_x是否都是内联的,这样它就会转换成内联汇编代码来对这两个组件求和?
这看起来像一个微不足道的例子,但我使用的是一个在模板中定义了维数的向量类,所以迭代向量上的操作看起来有点像这样。
发布于 2015-05-19 18:46:09
inline只是对编译器的一个提示。编译器是否真正内联函数则是另一个问题。对于gcc来说,有一个always inline属性来强制执行此操作。
__attribute__((always_inline));通过始终内联,你应该实现你所描述的(代码生成,就好像它是在一个函数中编写的一样)。
但是,对于编译器应用的所有优化和转换,只有检查生成的代码(程序集)才能确定
发布于 2015-05-19 18:45:14
是,内联可以递归应用。
您在这里执行的整个操作集都可以在调用点内联。
请注意,这与您使用inline关键字没有多大关系,该关键字(除了对ODR的影响之外--这一点非常明显)只是一个提示,目前在实际内联时通常忽略该关键字。函数将被内联,因为您聪明的编译器可以看到它们是很好的候选函数。
您可以实际知道它是否正在执行此操作的唯一方法是自己检查生成的程序集。
发布于 2015-05-19 18:50:02
那得看情况。inline只是对编译器的一个提示,它可能想要考虑内联该函数。编译器完全可以内联这两个调用,但这取决于实现。
作为一个例子,这里有一些来自GCC的美化汇编输出,其中包含和不包含这个简单程序的inline:
int main()
{
vec a;
vec b;
std::cin >> a.x;
std::cin >> a.y;
sum(b,a,a);
std::cout << b.x << b.y;
return 0;
}使用内联:
main:
subq $40, %rsp
leaq 16(%rsp), %rsi
movl std::cin, %edi
call std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
leaq 24(%rsp), %rsi
movl std::cin, %edi
call std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
movsd 24(%rsp), %xmm0
movapd %xmm0, %xmm1
addsd %xmm0, %xmm1
movsd %xmm1, 8(%rsp)
movsd 16(%rsp), %xmm0
addsd %xmm0, %xmm0
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
movsd 8(%rsp), %xmm0
movq %rax, %rdi
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
movl $0, %eax
addq $40, %rsp
ret
subq $8, %rsp
movl std::__ioinit, %edi
call std::ios_base::Init::Init()
movl $__dso_handle, %edx
movl std::__ioinit, %esi
movl std::ios_base::Init::~Init(), %edi
call __cxa_atexit
addq $8, %rsp
ret没有:
sum_x(vec&, vec&, vec&):
movsd (%rsi), %xmm0
addsd (%rdx), %xmm0
movsd %xmm0, (%rdi)
ret
sum(vec&, vec&, vec&):
movsd (%rsi), %xmm0
addsd (%rdx), %xmm0
movsd %xmm0, (%rdi)
movsd 8(%rsi), %xmm0
addsd 8(%rdx), %xmm0
movsd %xmm0, 8(%rdi)
ret
main:
pushq %rbx
subq $48, %rsp
leaq 32(%rsp), %rsi
movl std::cin, %edi
call std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
leaq 40(%rsp), %rsi
movl std::cin, %edi
call std::basic_istream<char, std::char_traits<char> >& std::basic_istream<char, std::char_traits<char> >::_M_extract<double>(double&)
leaq 32(%rsp), %rdx
movq %rdx, %rsi
leaq 16(%rsp), %rdi
call sum(vec&, vec&, vec&)
movq 24(%rsp), %rbx
movsd 16(%rsp), %xmm0
movl std::cout, %edi
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
movq %rbx, 8(%rsp)
movsd 8(%rsp), %xmm0
movq %rax, %rdi
call std::basic_ostream<char, std::char_traits<char> >& std::basic_ostream<char, std::char_traits<char> >::_M_insert<double>(double)
movl $0, %eax
addq $48, %rsp
popq %rbx
ret
subq $8, %rsp
movl std::__ioinit, %edi
call std::ios_base::Init::Init()
movl $__dso_handle, %edx
movl std::__ioinit, %esi
movl std::ios_base::Init::~Init(), %edi
call __cxa_atexit
addq $8, %rsp
ret正如您所看到的,当被要求时,GCC内联了这两个函数。
如果您的程序集有点生疏,只需注意在第二个版本中存在并调用了sum,但在第一个版本中没有。
https://stackoverflow.com/questions/30323325
复制相似问题