Solved

Copy constructor - query

Posted on 2004-10-09
15
249 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

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

[Live Webinar] The Cloud Skills Gap

As Cloud technologies come of age, business leaders grapple with the impact it has on their team's skills and the gap associated with the use of a cloud platform.

Join experts from 451 Research and Concerto Cloud Services on July 27th where we will examine fact and fiction.

Question has a verified solution.

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

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

626 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