C ++ const引用参数优化

时间:2014-09-02 06:36:57

标签: c++ optimization reference 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引用而被优化下来?

2 个答案:

答案 0 :(得分: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);   
}

这样编译和解散:

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的调用和两个构造函数调用都已内联。

您的编译器可能会有所不同。

答案 1 :(得分:-2)

第二个函数使用RectI构造函数创建一个RectI类型的对象,并将常量引用传递给第一个函数。该对象实际上已创建。

希望有所帮助。

卡尔斯。