Copy constructor doesn't get called when initialized by functionreturning object of same class

A

abhash

I am bit puzzled at the following piece of code I tried:

----------------------------------------------------------------------------------
#include <iostream>
using namespace std;

class Test {
public:
Test() { cout<<"Cons\n";}
Test(Test& a) { cout<<"Copy cons\n";}

};

Test fun()
{
return Test();

}

int main()
{
cout<<"First way of initialization\n";
Test t1;
Test t2 = t1;

cout<<"\nSecond way of initialization\n";
Test t3 = fun();
return 0;

}

OUTPUT (when compiled on CC compiler) :

First way of initialization
Cons
Copy cons

Second way of initialization
Cons
------------------------------------------------------------------------------------

I am intrigued why second initialization doesn't call copy
constructor ?
Aren't we passing the temporary object returned by fun() call to the
t3 for copying ?
 
I

Ian Collins

abhash said:
I am bit puzzled at the following piece of code I tried:
<snip>

I am intrigued why second initialization doesn't call copy
constructor ?
Aren't we passing the temporary object returned by fun() call to the
t3 for copying ?

Google for "C++ RVO"
 
S

sumsin

I am bit puzzled at the following piece of code I tried:

----------------------------------------------------------------------------------
#include <iostream>
using namespace std;

class Test {
public:
Test() { cout<<"Cons\n";}
Test(Test& a) { cout<<"Copy cons\n";}

This is not the right syntax for copy constructor. It should be like:

Test(const Test& a)
 
M

Mirco Wahab

abhash said:
I am bit puzzled at the following piece of code I tried:
...
#include <iostream>
using namespace std;
[snipped]
First way of initialization
Cons
Copy cons

Second way of initialization
Cons
...
I am intrigued why second initialization doesn't call copy
constructor ?
Aren't we passing the temporary object returned by fun() call to the
t3 for copying ?

Why should it? It's not initialized from an
instantiated object. This question (together
w/RVO) has been discussed frequently, eg.
here: http://forums.msdn.microsoft.com/en-US/vclanguage/thread/ac6e87ce-57c8-4916-ac29-fa083cdb94b3/

BTW, your code wouldn't compile on my gcc (4.3.1)
I had to modify it like:

...
class Test {
public:
Test() { cout<<"Cons\n";}
Test(const Test& a) { cout<<"Copy cons\n";}
};
...

so the /const/ was required to get disambiguation?
I'm not sure if this as required now so in the
standard, maybe the experts can say a word.

Regards

Mirco
 
J

James Kanze

But since those "thousands of lines of code" should do nothing
but than copy the internal state of the object, the object
created by RVO should have state identical to what its state
would be if your copy constructor had been invoked.

But that's not a requirement.
Hence, the "O" (Optimization) in RVO.

The word "bug" isn't correct, because it is an intentional
compromise. RVO definitly violates the basic C++ object model.
On the other hand, it can make a significant difference in
performance with most compilers, AND it shouldn't make a
significant difference in the behavior of a well designed and
written program.
 
D

Daniel Pitts

James said:
But that's not a requirement.
Its not an enforced requirement, but neither is proper synchronization
in multi-threaded applications. You'll just be sorry if you don't follow
it, but the compiler will let you do whatever you want. Point gun at
foot and pull trigger.
The word "bug" isn't correct, because it is an intentional
compromise. RVO definitly violates the basic C++ object model.
On the other hand, it can make a significant difference in
performance with most compilers, AND it shouldn't make a
significant difference in the behavior of a well designed and
written program.
I'm not sure how to respond to this, I haven't been into the depths of
C++ development long enough to have an opinion on "basic C++ object
model", and "the behavior of a well designed and written program". I
think I agree with your second point, but I'm not sure that the basic
C++ object model is that well defined.

It does make me wonder if RVO has ever interacted poorly with RAII
though. Not sure they ever really meet, but if they did, I could see
anguish and surprise :)
 
J

James Kanze

Its not an enforced requirement, but neither is proper
synchronization in multi-threaded applications. You'll just be
sorry if you don't follow it, but the compiler will let you do
whatever you want. Point gun at foot and pull trigger.

There's a difference. The lack of proper synchronization in
multi-threaded applications is undefined behavior. A copy
constructor which doesn't copy, or does more than just copy, is
more a style issue; it will confuse the maintenance programmers
to no end, but hey, that's their problem, not yours:). There's
also the fact that "proper synchronization" is rigorously
defined, where as what exactly it means to copy may depend on
the application. (I have at least one case where a copy
constructor does modify the logical internal state of the copied
object.)

There's one other major difference, too: lack of proper
synchronization is more or less existing practice (which is one
reason why so many programs crash all the time), where as a copy
constructor which doesn't copy is really rare (in my experience,
and supposing the appropiate definition of "copy").
I'm not sure how to respond to this, I haven't been into the
depths of C++ development long enough to have an opinion on
"basic C++ object model", and "the behavior of a well designed
and written program". I think I agree with your second point,
but I'm not sure that the basic C++ object model is that well
defined.

It's very rigorously defined, the copy constructor is a
constructor, and while it can be provided by the compiler, it
has no other particular privileges nor, as far as the language
itself is concerned, responsibilities.
It does make me wonder if RVO has ever interacted poorly with
RAII though. Not sure they ever really meet, but if they did,
I could see anguish and surprise :)

Most of the time, of course, RAII classes don't support copy.
But there are exceptions, some of which (e.g. boost::shared_ptr)
are widely used. The standards committee very definitely
considered these, and if RVO does cause problems with them, it
should be considered a bug in the standard. (I think the way
RVO was originally specified did cause problems in some cases.
And the specification was modified so that it wouldn't.)
 

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,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top