Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 254
  • Last Modified:

Copy constructor - query

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
mrwad99
Asked:
mrwad99
  • 6
  • 5
  • 4
2 Solutions
 
efnCommented:
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
 
rstaveleyCommented:
You'll find that most compilers do return value optimisation.
0
 
mrwad99Author Commented:
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!

 
rstaveleyCommented:
Should? No. Legitimately could be... yes.
0
 
rstaveleyCommented:
If your compiler doesn't do return value optimisation, though, you ought to consider a different vendor.
0
 
mrwad99Author Commented:
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
 
efnCommented:
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
 
rstaveleyCommented:
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
 
efnCommented:
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
 
rstaveleyCommented:
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
 
mrwad99Author Commented:
>> 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
 
efnCommented:
> 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
 
mrwad99Author Commented:
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
 
rstaveleyCommented:
Yes
0
 
mrwad99Author Commented:
Many thanks both !
0

Featured Post

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

  • 6
  • 5
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now