2014-09-02 94 views
1

我在理解這將如何編譯時遇到了一些麻煩,並且我不明白程序集輸出足以判斷。C++ const參考參數優化

struct RectI { 
    int left; int top; int right; int bottom; 

    ... 

    BOOL Intersects(const RectI& rc) 
    { 
     return (!(left > rc.right || right < rc.left || top > rc.bottom || bottom < rc.top)); 
    } 
    BOOL Intersects(int l, int t, int r, int b) 
    { 
     return Intersects(RectI(l, t, r, b)); 
    } 
}; 

對於方法Intersects(int, int, int, int),它立即調用Intersects(const RectI&)。這是否需要在內存中創建一個全新的結構 ,然後將其構造並傳遞給Intersects(const RectI&)或者由於該參數是一個const引用,這會被優化嗎?

+1

它必須像創建一個臨時表現一樣。臨時創建是否可以優化取決於其他因素,例如RectI的構造函數和析構函數是否有副作用。 – 2014-09-02 06:41:49

+0

構造函數非常簡單,它只是將四個值分配給成員數據並且也是內聯的。 – 2014-09-02 06:42:39

+1

const&不會停止函數調用期間的對象創建。 – 2014-09-02 06:43:47

回答

4

應該內聯和優化,假設構造函數(你忘了給我們看)很簡單,並定義爲內聯。但唯一確定的方法是查看組件輸出。

我放在一起這個測試用例:

#include <iostream> 
typedef bool BOOL; 

struct RectI { 
    int left; int top; int right; int bottom; 

    RectI(int l, int t, int r, int b) : left(l), top(t), right(r), bottom(b) {} 

    BOOL Intersects(const RectI& rc) { return (!(left > rc.left || right < rc.right || top > rc.bottom || bottom < rc.top)); } 
    BOOL Intersects(int l, int t, int r, int b) { return Intersects(RectI(l, t, r, b)); } 
}; 

int main() 
{ 
    // Read from input, to prevent the entire calculation being optimised out 
    int l,t,r,b; 
    std::cin >> l >> t >> r >> b; 

    RectI rt(l,t,r,b);  
    return rt.Intersects(1,2,3,4); 
} 

編譯正是如此dissassembled:

g++ -O3 test.cpp 
objdump -dC a.out 

00000000004005d0 <main>: 
    4005d0:  48 83 ec 18    sub $0x18,%rsp 
    4005d4:  bf 40 10 60 00   mov $0x601040,%edi 
    4005d9:  48 89 e6    mov %rsp,%rsi 
    4005dc:  e8 df ff ff ff   callq 4005c0 <std::istream::operator>>(int&)@plt> 
    4005e1:  48 8d 74 24 04   lea 0x4(%rsp),%rsi 
    4005e6:  48 89 c7    mov %rax,%rdi 
    4005e9:  e8 d2 ff ff ff   callq 4005c0 <std::istream::operator>>(int&)@plt> 
    4005ee:  48 8d 74 24 08   lea 0x8(%rsp),%rsi 
    4005f3:  48 89 c7    mov %rax,%rdi 
    4005f6:  e8 c5 ff ff ff   callq 4005c0 <std::istream::operator>>(int&)@plt> 
    4005fb:  48 8d 74 24 0c   lea 0xc(%rsp),%rsi 
    400600:  48 89 c7    mov %rax,%rdi 
    400603:  e8 b8 ff ff ff   callq 4005c0 <std::istream::operator>>(int&)@plt> 
    400608:  31 c0     xor %eax,%eax 
    40060a:  83 3c 24 01    cmpl $0x1,(%rsp) 
    40060e:  8b 74 24 0c    mov 0xc(%rsp),%esi 
    400612:  8b 54 24 08    mov 0x8(%rsp),%edx 
    400616:  8b 4c 24 04    mov 0x4(%rsp),%ecx 
    40061a:  7e 05     jle 400621 <main+0x51> 
    40061c:  48 83 c4 18    add $0x18,%rsp 
    400620:  c3      retq 
    400621:  83 fa 02    cmp $0x2,%edx 
    400624:  7e f6     jle 40061c <main+0x4c> 
    400626:  83 f9 04    cmp $0x4,%ecx 
    400629:  7f f1     jg  40061c <main+0x4c> 
    40062b:  31 c0     xor %eax,%eax 
    40062d:  83 ee 01    sub $0x1,%esi 
    400630:  0f 9f c0    setg %al 
    400633:  eb e7     jmp 40061c <main+0x4c> 
    400635:  66 66 2e 0f 1f 84 00 data32 nopw %cs:0x0(%rax,%rax,1) 
    40063c:  00 00 00 00 

輸出你可以看到有四個函數調用(在callq指令)從輸入中讀取;其餘部分由內聯比較組成,沒有進一步的函數調用:內聯了對Intersects和這兩個構造函數調用的兩個調用。

您的編譯器可能會有所不同。

-2

第二個函數使用RectI構造函數創建一個RectI類型的對象,並將一個常量引用傳遞給第一個函數。該對象實際上已創建。

希望有所幫助。

Carles。