By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,089 Members | 1,367 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,089 IT Pros & Developers. It's quick & easy.

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

P: n/a
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 ?
Jun 27 '08 #1
Share this Question
Share on Google+
10 Replies


P: n/a
abhash wrote:
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"

--
Ian Collins.
Jun 27 '08 #2

P: n/a
On Jun 12, 11:05 am, abhash <amit.abh...@gmail.comwrote:
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)
>
};

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 ?
Jun 27 '08 #3

P: n/a
On 2008-06-12 10:13:56 +0200, sumsin <su*******@gmail.comsaid:
On Jun 12, 11:05 am, abhash <amit.abh...@gmail.comwrote:
>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)
While it's unusual to have a copy constructor that takes its argument
by non-const reference, it is, nonetheless, a copy constructor.

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

Jun 27 '08 #4

P: n/a
abhash wrote:
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-...-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
Jun 27 '08 #5

P: n/a
On Jun 12, 1:01 pm, Ian Collins <ian-n...@hotmail.comwrote:
abhash wrote:
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"

--
Ian Collins.
Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:

http://www.informit.com/guides/conte...lus&seqNum=199

-Amit
Jun 27 '08 #6

P: n/a
On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
>Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:

http://www.informit.com/guides/conte...lus&seqNum=199
RVO is a bug in the C++ language. Your copy constructor could contain
thousands of lines of code (code with side effects) which may be
blissfully elided by a compiler in the mood.

--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 27 '08 #7

P: n/a
Roland Pibinger wrote:
On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
>>Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:

http://www.informit.com/guides/conte...lus&seqNum=199

RVO is a bug in the C++ language. Your copy constructor could contain
thousands of lines of code (code with side effects) which may be
blissfully elided by a compiler in the mood.
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. Hence, the "O" (Optimization) in RVO.
--
Fran
Jun 27 '08 #8

P: n/a
On Jun 13, 4:11 am, Francis Litterio <em...@not.availablewrote:
Roland Pibinger wrote:
On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
>Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:
>http://www.informit.com/guides/conte...lus&seqNum=199
RVO is a bug in the C++ language. Your copy constructor
could contain thousands of lines of code (code with side
effects) which may be blissfully elided by a compiler in the
mood.
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.

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orient�e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S�mard, 78210 St.-Cyr-l'�cole, France, +33 (0)1 30 23 00 34
Jun 27 '08 #9

P: n/a
James Kanze wrote:
On Jun 13, 4:11 am, Francis Litterio <em...@not.availablewrote:
>Roland Pibinger wrote:
>>On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:
>>>http://www.informit.com/guides/conte...lus&seqNum=199
>>RVO is a bug in the C++ language. Your copy constructor
could contain thousands of lines of code (code with side
effects) which may be blissfully elided by a compiler in the
mood.
>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.
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.
>
>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.
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 :-)

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Jun 27 '08 #10

P: n/a
On Jun 14, 8:20 pm, Daniel Pitts
<newsgroup.spamfil...@virtualinfinity.netwrote:
James Kanze wrote:
On Jun 13, 4:11 am, Francis Litterio <em...@not.availablewrote:
Roland Pibinger wrote:
On Thu, 12 Jun 2008 11:47:10 -0700 (PDT), abhash wrote:
Thanks Ian for pointing to RVO term. Found quite a lucid explanation
for it here:
>>>http://www.informit.com/guides/conte...lus&seqNum=199
>RVO is a bug in the C++ language. Your copy constructor
could contain thousands of lines of code (code with side
effects) which may be blissfully elided by a compiler in the
mood.
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.
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").
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.

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.)

--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique oriente objet/
Beratung in objektorientierter Datenverarbeitung
9 place Smard, 78210 St.-Cyr-l'cole, France, +33 (0)1 30 23 00 34
Jun 27 '08 #11

This discussion thread is closed

Replies have been disabled for this discussion.