2012-11-14 30 views
8

我看到一個奇怪的問題,如果我定義了析構函數,那麼成員方法沒有被內聯。定義析構函數可以防止成員函數被內聯

示例代碼:

#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來幫助說服它在沒有運氣的情況下內聯該方法。

我對程序集不夠熟悉,無法確切知道它正在嘗試做什麼,也許明天我會試圖弄明白,如果給出任何提示。任何人都可以闡明爲什麼定義一個空的析構函數會阻止該方法被內聯?

編輯[17/11/2012]

我更新了上面的代碼要簡單得多(最初我正在處理我的Vector類)。

從成員方法返回一個原始類型似乎正確地內聯,這只是一個問題,當我返回我的類的一個實例。

+0

我的解決方案有幫助嗎? –

回答

2

的Visual Studio治療類帶有析構函數(空或不)爲「複雜的」,他們將更有可能放棄某些優化。如果您的課程簡單且速度敏感,請使用默認析構函數。

+0

若要擴展您的答案,以下MSDN文章[內嵌,__inline,__forceinline](http://msdn.microsoft.com/en-us/library/z8y1yy88(v = vs.71).aspx)解釋說,編譯器如果函數按值返回一個不可放開的對象,用/ GX,/ EHs或/EHa編譯時不能內聯一個函數。 看來我的對象被定義爲可放開的,因爲它有一個用戶定義的析構函數儘管它是空的)。禁用「啓用C++異常」標誌允許再次內聯對象。 – Gareth

+0

NB。返回一個引用(對象)允許它也被內聯。 – Gareth

0

在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); 
} 
+0

不完全回答爲什麼編譯器不內聯這個方法,但是我在處理我的Vector類時肯定會使用它,因爲我喜歡這種方法。 – Gareth

相關問題