Solved

Copy constructor - query

Posted on 2004-10-09
15
209 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
  • 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
 
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 75 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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
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 25 total points
ID: 12272059
Yes
0
 
LVL 19

Author Comment

by:mrwad99
ID: 12272128
Many thanks both !
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will be introduced to the technique of using vectors in C++. The video will cover how to define a vector, store values in the vector and retrieve data from the values stored in the vector.

708 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now