定义析构函数可以防止成员函数内联

Defining a destructor prevents member functions being inlined

本文关键字:成员 函数 析构函数 定义      更新时间:2023-10-16

我看到一个奇怪的问题,如果我定义了析构函数,by成员方法就不会内联。

示例代码:

#include <cstdio>
class Foo
{
public:
Foo(int arg) : data(arg) {}
~Foo(void) {}
Foo bar(void) const { return Foo(7); }
int data;
};
int main(void)
{
Foo a(3);
Foo b = a.bar();
printf ("%i", b.data);
}

如果使用默认的析构函数,我会得到这样的结果:

main:
sub         rsp,28h  
lea         rcx,[string "%i" (013FB8ADA0h)]  
mov         edx,7  
call        printf (013FB81068h)  
xor         eax,eax  
add         rsp,28h  
ret  

但是,如果我定义自己的空白析构函数,如上面的代码所示:

Foo::bar:
mov         dword ptr [rdx],7  
mov         rax,rdx  
ret  
main:
sub         rsp,28h  
lea         rdx,[b]  
call        Foo::bar (013FA11000h)  
mov         edx,dword ptr [b]  
lea         rcx,[string "%i" (013FA1ADA0h)]  
call        printf (013FA11088h)  
xor         eax,eax  
add         rsp,28h  
ret  

使用Visual Studio 2012(v110)编译为发布版本,但也尝试过Visual Studio 2010(v100)。我尝试设置/Ob2来帮助说服它内联该方法,但没有成功。

我对汇编不够熟悉,不知道它到底在做什么,也许明天我会想办法弄清楚,看看它是否能给我任何提示。有人能解释为什么定义一个空的析构函数会阻止方法内联吗?

编辑[2012/11]我更新了上面的代码,使其简单得多(最初我正在处理Vector类)。

从成员方法返回基元类型似乎得到了正确的内联,这只是当我返回类的实例时的问题。

Visual Studio将具有析构函数(无论是否为空)的类视为"复杂"类,它们更有可能放弃某些优化。如果您的类简单且对速度敏感,请使用默认的析构函数。

在VS 2010中,编译器似乎在编译时计算最终值,并将其加载到a值的堆栈中
按以下方式修改代码确实启用了此优化,并定义了析构函数:

inline void operator = (const __m128 v)
{
data = v;
}
inline __m128 operator* (const Vector4& a) const
{ 
return _mm_mul_ps(data, a.data); 
}