extended RVO

M

Marc

Hello,

the example wikipedia gives for return value optimization (copy elision)
is the following:

#include <iostream>

struct C
{
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};

C f()
{
return C();
}

int main()
{
std::cout << "Hello World!\n";
C obj = f();
}

which, with the 4 compilers I tried, doesn't perform any copy (nice!).
Now if I create a wrapper for C:

struct D : C
{
D(){}
D(int):C(f()){}
D(C const& c):C(c){}
// it doesn't matter if I write D(C c):C(c){} instead
};

int main()
{
D obj = 3; // no copy (except with sunpro)
D obj = f(); // 1 COPY :-(
}

I am trying to understand if the compiler could (legally and
technically) avoid that copy. I believe it would be legal:

"when a temporary class object that has not been bound to a reference
(12.2) would be copied to a class object with the same cv-unqualified
type, the copy operation can be omitted by constructing the temporary
object directly into the target of the omitted copy"

but, as opposed to the regular RVO optimization, the compiler first
needs to inline the call to D::D to have enough information to elide the
copy, which is too late with the organization of most compilers.

This means that if I really want to limit copying, I need to make sure
classes like D have "emplace"-like constructors.

Is my understanding correct? Any idea how hard it would be to add this
kind of optimization to a compiler? (for instance some heuristic early
inlining of things that are not copy/move constructors, before the copy
elision checks, possibly helped by a hard_inline attribute)
 
J

Juha Nieminen

Marc said:
D(C const& c):C(c){}

Note that that is not a copy constructor, but a regular constructor.
The compiler is not making a copy, it's calling that constructor. The
RVO is still being performed, but you are confusing the construction
of D with copying the object (which is not what's happening).
 
M

Marc

Juha said:
Note that that is not a copy constructor, but a regular constructor.
The compiler is not making a copy, it's calling that constructor. The
RVO is still being performed, but you are confusing the construction
of D with copying the object (which is not what's happening).

Er, yes, I know this is not a copy constructor :)

However, the only effect of this code is to call C's copy constructor.
It is thus a bit sad that it has to introduce an extra copy to do so. I
could even write:
C c=f();
D& d=(D&)c;
which doesn't do any copy. But is ugly and probably not legal, although
I doubt it fails anywhere.
 
J

Juha Nieminen

Marc said:
Er, yes, I know this is not a copy constructor :)

However, the only effect of this code is to call C's copy constructor.
It is thus a bit sad that it has to introduce an extra copy to do so. I
could even write:
C c=f();
D& d=(D&)c;
which doesn't do any copy. But is ugly and probably not legal, although
I doubt it fails anywhere.

The D object has to be constructed somehow. A constructor *has* to be
called for this. The only constructor you have provided is the one taking
a C reference as parameter, so that's what the compiler has to use.

If copy-constructing C is heavy, you could perhaps avert the cost in
this case by using a move constructor (of C) instead, once C++0x somes
out.
 
M

Marc

Marc said:
the example wikipedia gives for return value optimization (copy elision)
is the following:

#include <iostream>

struct C
{
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
};

C f()
{
return C();
}

int main()
{
std::cout << "Hello World!\n";
C obj = f();
}

which, with the 4 compilers I tried, doesn't perform any copy (nice!).
Now if I create a wrapper for C:

struct D : C
{
D(){}
D(int):C(f()){}
D(C const& c):C(c){}
// it doesn't matter if I write D(C c):C(c){} instead
};

int main()
{
D obj = 3; // no copy (except with sunpro)
D obj = f(); // 1 COPY :-(
}

I am trying to understand if the compiler could (legally and
technically) avoid that copy.

I just found out that this is CORE issue 1049, which shows that it is
currently illegal, but would be technically feasible. I certainly hope
it will be fixed as recommended in the text of the issue.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,077
Latest member
SangMoor21

Latest Threads

Top