2014-09-02 96 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。