Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Difference between if and ternary operator

120 views
Skip to first unread message

peter....@gmail.com

unread,
May 20, 2012, 11:08:46 AM5/20/12
to
Hi!

The output of the example below is "CopyMove". Should not it be "MoveMove" ?
If not, why is it so ? I tried this with GCC 4.7, VS 10, and VS11 Beta.
All the compilers return "CopyMove".

Thank you very much for the answer.

PK.

// ---
#include <iostream>
#include <cstdlib>
using namespace std;
struct CBigData
{
CBigData() {}
CBigData(const CBigData &)
{
cout << "Copy";
}
CBigData(CBigData &&)
{
cout << "Move";
}
};

CBigData MoveTest()
{
CBigData b1, b2;
return rand() % 2 ? b1 : b2;
}

CBigData MoveTest2()
{
CBigData b1, b2;
if (rand() % 2)
return b1;
else
return b2;
}

int main(int argc, char* argv[])
{
CBigData d(MoveTest());
CBigData d2(MoveTest2());
return 0;
}


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Francis Glassborow

unread,
May 20, 2012, 3:12:36 PM5/20/12
to
On 20/05/2012 16:08, peter....@gmail.com wrote:
> Hi!
>
> The output of the example below is "CopyMove". Should not it be
> "MoveMove" ? If not, why is it so ? I tried this with GCC 4.7, VS
> 10, and VS11 Beta. All the compilers return "CopyMove".
>
> Thank you very much for the answer.

In the case of the if statement each case is a direct return of and
object of type CBigData (by the way, it might have been better to
actually provide some substantial data to prevent compilers spotting
that there is nothing to do) and so the code can safely use the move
ctor. However in the case of the ?: that is an expression that the
compiler must evaluate BEFORE the return and at that point the local
objects have not ended their lives. I suspect that what you are seeing
is the consequence of an optimising compiler not going the whole
way. It copies when evaluating the query but uses the storage for the
return to hold that copy.

Gene Bushuyev

unread,
May 21, 2012, 3:31:14 PM5/21/12
to
On May 20, 8:08 am, peter.kub...@gmail.com wrote:
> Hi!
>
> The output of the example below is "CopyMove". Should not it be
> "MoveMove" ? If not, why is it so ? I tried this with GCC 4.7, VS
> 10, and VS11 Beta. All the compilers return "CopyMove".

In a situation when function returns an object of the same type as the
return type, compiler follows three step procedure: 1) elide copy on
return; if can't 2) move on return; if can't 3) copy on return. This
is probably the only situation (a similar case when throwing an
object) when compiler is allowed to move from lvalue. On the other
hand, when compiler returns an expression, it's up to optimizer to
figure out the best way following as if rule.

> Thank you very much for the answer.
>
> PK.
>
> // ---
> #include <iostream>
> #include <cstdlib>
> using namespace std;
> struct CBigData
> {
> CBigData() {}
> CBigData(const CBigData &)
> {
> cout << "Copy";
> }
> CBigData(CBigData &&)
> {
> cout << "Move";
> }
>
> };
>
> CBigData MoveTest()
> {
> CBigData b1, b2;
> return rand() % 2 ? b1 : b2;
>
> }

This returns an expression, b1 and b2 are lvalues, they cannot be
moved from, so compiler uses copy.

> CBigData MoveTest2()
> {
> CBigData b1, b2;
> if (rand() % 2)
> return b1;
> else
> return b2;
>
> }

And this is the case of returning an object, compiler is allowed to
elide copy or move from lvalue on return.

peter....@gmail.com

unread,
May 22, 2012, 3:06:23 PM5/22/12
to
So, in this case I should prefer if over the ternary operator, as the
optimization is easier. Hopefully, the optimizers will soon handle this.
I was just puzzled by the fact that all compilers used the "copy" approach,
so I was thinking there might be some wording in the standard that prevents it.

Anyway, thank you very much for your answer.

Peter Kubini

Pete Becker

unread,
May 22, 2012, 8:12:21 PM5/22/12
to
On 2012-05-22 19:06:23 +0000, peter....@gmail.com said:

> So, in this case I should prefer if over the ternary operator, as the
> optimization is easier.

Or you could make your intention explicit by calling std::move().

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)
0 new messages