Is a copy constructor needed for the return value optimization?

S

SzH

The code below demonstrates that the copy constructor of moo is not
called on the first line of main. In spite of this, g++ (version 4.1.2)
refuses to compile it if I make the copy constructor private. But the
Digital Mars compiler does not complain.

Which compiler is right? (And if gcc is right, why does this restriction
exist?)

Szabolcs

#include <iostream>

struct moo {
int data;

moo(int n) : data(n) {
std::cout << "constructor\n";
}

// private:
moo(const moo &m) : data(m.data) {
std::cout << "copy constructor\n";
}
};

moo fun() {
return moo(3);
}

int main() {
moo m = fun();
return 0;
}
 
P

Pete Becker

SzH said:
The code below demonstrates that the copy constructor of moo is not
called on the first line of main. In spite of this, g++ (version 4.1.2)
refuses to compile it if I make the copy constructor private. But the
Digital Mars compiler does not complain.

Which compiler is right? (And if gcc is right, why does this restriction
exist?)

Return value optimization, as the name says, is an optimization.
Optimizations should never make incorrect code compile, nor make valid
code fail to compile. Returning a result by value, as your function
does, requires copying the value, which in turn requires an accessible
copy constructor. When you make the copy constructor inaccessible you
cannot return an object of that type by value.

--

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

SzH

Pete said:
Return value optimization, as the name says, is an optimization.
Optimizations should never make incorrect code compile, nor make valid
code fail to compile. Returning a result by value, as your function
does, requires copying the value, which in turn requires an accessible
copy constructor. When you make the copy constructor inaccessible you
cannot return an object of that type by value.

I can not agree with this completely. If it was just a "normal"
optimisation then the result of the program should not depend on whether
the optimisation is performed or not. When I run the program, the line
"copy constructor" is not printed, so I can tell that the optimisation
was performed (i.e. the value was not copied).
 
V

Victor Bazarov

SzH said:
I can not agree with this completely. If it was just a "normal"
optimisation then the result of the program should not depend on
whether the optimisation is performed or not.

The Standard explicitly allows this kind of optimization regardless
of the presence of side effects in the constructor. BTW, RVO is just
about the only optimization the Standard actually defines. And it
has to do that explicitly to state the "regardless of side effects"
portion.
When I run the program,
the line "copy constructor" is not printed, so I can tell that the
optimisation was performed (i.e. the value was not copied).

So? It doesn't remove the requirement that the Standard sets forth.
The code is ill-formed _if_ the copy *cannot* be made should it be
necessary to make it.

V
 
S

SzH

Victor said:
The Standard explicitly allows this kind of optimization regardless
of the presence of side effects in the constructor. BTW, RVO is just
about the only optimization the Standard actually defines. And it
has to do that explicitly to state the "regardless of side effects"
portion.

Just to make sure that I understand this correctly:
So the Standard *allows* this optimisation, but it does not *require*
it. Is this right?

Could you please point me to the relevant section of the Standard?
Unfortunately I was unable to find it myself.
 
P

Pete Becker

SzH said:
I can not agree with this completely. If it was just a "normal"
optimisation then the result of the program should not depend on whether
the optimisation is performed or not. When I run the program, the line
"copy constructor" is not printed, so I can tell that the optimisation
was performed (i.e. the value was not copied).

That's a different issue: the compiler is allowed to skip the copy
constructor. That doesn't make the code without an accessible copy
constructor valid, though. As I said, the optimization doesn't turn
invalid code into valid code.

--

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

Victor Bazarov

SzH said:
Just to make sure that I understand this correctly:
So the Standard *allows* this optimisation, but it does not *require*
it. Is this right?
Yes.

Could you please point me to the relevant section of the Standard?
Unfortunately I was unable to find it myself.

12.8/15

V
 
R

Roland Pibinger

The Standard explicitly allows this kind of optimization regardless
of the presence of side effects in the constructor.

This should be regarded as bug in the C++ Standard.
 
J

James Kanze

I can not agree with this completely. If it was just a "normal"
optimisation then the result of the program should not depend on whether
the optimisation is performed or not.

Right. It's not normal optimization; it's a special hack. On
the other hand, it does seem reasonable to expect copy
constructors to copy.
When I run the program, the line "copy constructor" is not
printed, so I can tell that the optimisation was performed
(i.e. the value was not copied).

Correct. The standard explicitly allows this.

It doesn't change the fact that conceptually, a copy was
required; the standard just allows the compiler to ignore
observable behavior that occurs in the copy constructor and the
destructor. For purposes of optimization.
 
J

James Kanze

This should be regarded as bug in the C++ Standard.

Sort of. It's a hack. It was felt that it wouldn't make a
difference in well written C++ code (which is certainly true),
and that the optimization was too important to take support for
poorly written C++ into account. It's certain, however, that it
places games with the C++ object model.
 

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

Forum statistics

Threads
473,769
Messages
2,569,576
Members
45,054
Latest member
LucyCarper

Latest Threads

Top