http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57064



--- Comment #1 from Thiago Macieira <thiago at kde dot org> 2013-04-25 00:45:00 
UTC ---

Here's why I'm asking:



QString has members like:



    QString arg(int, [other parameters]) const;



Which are used like so:



    return QString("%1 %2 %3 %4").arg(42).arg(47).arg(-42).arg(-47);

    // returns "42 47 -42 -47"



Right now, each call creates a new temporary, which is required to do memory

allocation. I'd like to avoid the new temporaries by simply reusing the

existing ones:



    QString arg(int, [...]) const &; // returns a new copy

    QString &&arg(int, [...]) &&; // modifies this object, return *this;



When these two overloads are present, every other call will be to rvalue-ref

and the others to lvalue-ref. That is, the first call (right after the

constructor) calls arg()&&, which returns an rvalue-ref. The next call will be

to arg()&, which returns a temporary, making the third call to arg()&& again.



I can get the desired behaviour by using the overloads:



    QString arg(int, [...]) const &; // returns a new copy

    QString arg(int, [...]) &&; // returns a moved temporary via return

std::move(*this);



However, the side-effect of that is that we still have 4 temporaries too many,

albeit empty (moved-out) ones. You can see this by counting the number of calls

to the destructor:



$ ~/gcc4.8/bin/g++ -fverbose-asm -fno-exceptions -fPIE -std=c++11 -S -o -

-I$QTOBJDIR/include /tmp/test.cpp | grep -B1 call.*QStringD

        movq    %rax, %rdi      # tmp82,

        call    _ZN7QStringD1Ev@PLT     #

--

        movq    %rax, %rdi      # tmp83,

        call    _ZN7QStringD1Ev@PLT     #

--

        movq    %rax, %rdi      # tmp84,

        call    _ZN7QStringD1Ev@PLT     #

--

        movq    %rax, %rdi      # tmp85,

        call    _ZN7QStringD1Ev@PLT     #

Reply via email to