Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Copy constructor - query

Posted on 2004-10-09
15
Medium Priority
?
251 Views
Last Modified: 2010-04-01
Ah hello.

I feel a bit ashamed to ask this, since the answer is probably straight forward, but I guess this is one of those intricate little gems that you never consider until you have to...

I was taking some code apart involving copy constructors as follows:

class A
{
// other stuff

      static A Test() {  
            A a(10);
            return a;
      }
};

int main()
{
      A b = A::Test();
      return 0;
}

Now this is all incredibly simple stuff, but what I cannot see why is why the copy constructor is not called twice in this code (assume all functions have been added with appropriate 'cout' statements to show what is being called).  The way I see it is that the copy constructor first gets called when calling

return a;

since this is returning by value hence a copy is needed.  Now I figured that in the call of

b = A::Test()

which involves not the assignment operator but the copy constructor (since it is initialisation not assignment) we would call the copy constructor *again* to initialise 'b'.  *But this does not happen !*  And I know that 'b' is exactly the same as the object returned too.  I get exactly the same behaviour as if I just call

A::Test()

without using the return value.

Can someone please enlighten me ?

TIA
0
Comment
Question by:mrwad99
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 4
15 Comments
 
LVL 15

Expert Comment

by:efn
ID: 12267365
I think the answer is simply that the compiler is allowed to optimize away temporary objects.  In fact, if you changed Test to do this:

return A(10);

you might not see the copy constructor called at all.  The compiler could just construct the object in b's space.

References:

http://cpptips.hyperformix.com/cpptips/ret_val_opt

http://groups.google.com/groups?hl=en&lr=&selm=76u9oe%24gor%241%40brokaw.wa.com&rnum=2
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12267367
You'll find that most compilers do return value optimisation.
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12267393
Yeah that is right; there is no copy constructor being called when I just state

return A(10);

Now then, the crucial question remains, *was I correct in thinking that the copy constuctor should (in theory - putting all fancy optimisation aside) be called twice, most notably for the construction of b* ?
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 17

Expert Comment

by:rstaveley
ID: 12267419
Should? No. Legitimately could be... yes.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12267425
If your compiler doesn't do return value optimisation, though, you ought to consider a different vendor.
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12267442
Heh, it does support optimisation(VC++ 6.0) that is why I was not getting what I thought should be the required behaviour.

>> Should? No.

Why should it not ?

A b = A::Test();

is constructing an object by initialisation, not assignment, hence the copy constructor is being used.

return a;

is returning an object by value, so again the copy constructor is being called.

That makes two calls to the copy constructor.

If I am wrong correct me please, as I like to take things apart and hate being unsure of something.  But I am sure my reasoning is correct.
0
 
LVL 15

Accepted Solution

by:
efn earned 300 total points
ID: 12267671
Initialization does not always require a copy constructor call.  Section 12.8, clause 15 of the 2003 C++ standard ISO/IEC 14882 says:

"When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects.

...

This elision of copy operations is permitted in the following circumstances (which may be combined to eliminate multiple copies):

-- in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function’s return value

..."
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12267814
Actually...

     static A Test() {  
          A a(10);
          return a;
     }

... a is not an automatic object, so you'd expect a ctor for A and a ctor for b, but not the return value temporary object. Oddly enough this cropped up in another current thread to which you can see a simple little experiment I put together a few minutes ago. See http:/Q_21162108.html#12267755

[ BTW... I love the use of the word "elision" in the standard :-) ]
0
 
LVL 15

Expert Comment

by:efn
ID: 12268002
rs> a is not an automatic object

Why do you think that?  It looks pretty automatic to me:  local scope, not static, not extern.
0
 
LVL 17

Expert Comment

by:rstaveley
ID: 12268362
You're right efn it is an automatic object. I'm forgetting my basics.

I've got a vague confused memory of there being a difference between a named variable and a temporary object in the context of optimisation, which is illustrated by http:/Q_21162108.html#12267755 (my addled brain had automatic=unnamed i.e. temporary, which it isn't) ... but it is late on a Saturday night and I don't think I'm in the right frame of mind to wade through the C++ standard %-)
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12271532
>> return A(10);

>> you might not see the copy constructor called at all.  The compiler could just construct the object in b's space.

So that means that there is no explicit call to any constructor of any kind; it is as if the temporary returned 'becomes' b just like that ?
0
 
LVL 15

Expert Comment

by:efn
ID: 12271931
> So that means that there is no explicit call to any constructor of any kind; it is as if the temporary returned 'becomes' b just like that ?

No, the A::A(int) constructor would be used to construct b.  Just the copy would be avoided.
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12271968
Yeah, but what I meant was that there will only be only be *one* call to the constructor; effectively the object returned in

return A(10)

*is* b

due to compiler optimisation ?
0
 
LVL 17

Assisted Solution

by:rstaveley
rstaveley earned 100 total points
ID: 12272059
Yes
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12272128
Many thanks both !
0

Featured Post

VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

722 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question