4

When I read about copy initializing vs direct initializing here. copy constructor should call in copy initializing. why here copy constructor not calling?

#include <iostream>

using namespace std;

class A{};

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
B(const B &b){cout << "B copy constructor" << endl;}
};

int main(){
A a;
B b = a;
return 0;
}
Community
  • 1
  • 1
Nayana Adassuriya
  • 23,596
  • 30
  • 104
  • 147

2 Answers2

5

Copy initialization is still subject to copy elision, and I'm guessing that's what's happening. Theoretically, a temporary B is constructed from a and the the copy constructor is used to create b from the temporary. In practice, the copy can be optimized out.

To test this, you can make the copy constructor private:

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
private:
B(const B &b){cout << "B copy constructor" << endl;}
};

and get a compilation error. This means the compiler expects the copy constructor to be accessible, but is not required to call it.

Copy elision is the only case where observed behavior can be altered.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • Read that again, Luchian. I read it and got that the cpyctor was NOT being called (which implies what you and I would expect, but he didn't). – WhozCraig Oct 02 '12 at 07:32
  • 2
    @WhozCraig the copy constructor is not being called because it's optimzied out. – Luchian Grigore Oct 02 '12 at 07:32
  • Why would it be called at all ?? There is no 'B' on the right side of that init. – WhozCraig Oct 02 '12 at 07:33
  • 1
    @WhozCraig because that's what copy initialization means - read my answer again and read up on copy initialization. – Luchian Grigore Oct 02 '12 at 07:34
  • Wow. thanks so much. I've studied and used this language a *long* time and never saw that (of course, I've never saw the need to *do* it either. Thanks, Luchian. – WhozCraig Oct 02 '12 at 07:36
  • 1
    @WhozCraig sure. IMO, there's not much motivation behind having them behave differently. Especially since you can't even rely on a temporary being created (like the code in the question). Related - http://stackoverflow.com/questions/11223285/whats-the-motivation-between-having-copy-and-direct-initialization-behave-diffe – Luchian Grigore Oct 02 '12 at 07:37
  • Perhaps the reason I've never ran into this in all this time is because I would have just B b(a); and called it good. Again, thanks for the info, and the link. – WhozCraig Oct 02 '12 at 07:39
  • @LuchianGrigore: Actually if i make cpyctor privet it gets compilation error. Ok I will accept your answer (compiler optimized). Is this in C++ standers? or it implemented by compiler developers? Can same thing happen when pass by value or return by value? – Nayana Adassuriya Oct 02 '12 at 07:41
  • 1
    @NayanaAdassuriya exactly. If you make it private, you'll get a compilation error. That's what should happen (and the explanation is in the answer). Yes, it's in the standard, and it's perfectly valid. Yes, copy elision can happen at any time, with a smart enough compiler. – Luchian Grigore Oct 02 '12 at 07:43
5

This is Copy ElisionRef 1:.
Copy constructor calls while generating temporaries might be optimized by the compiler by creating objects inline and it is explicitly allowed by the C++ Standard.

This is nicely demonstrated in the standard with an example as well:

C++03 Standard 12.2 Temporary objects [class.temporary]
Para 2:

[Example:
class X {
    // ...
    public:
    // ...
    X(int);
    X(const X&);
    ˜X();
};
X f(X);

void g()
{
    X a(1);
    X b = f(X(2));
    a = f(a);
}

Here, an implementation might use a temporary in which to construct X(2) before passing it to f() using X’s copy-constructor; alternatively, X(2) might be constructed in the space used to hold the argument. Also, a temporary might be used to hold the result of f(X(2)) before copying it to `b usingX’s copyconstructor; alternatively,f()’s result might be constructed in b. On the other hand, the expressiona=f(a)requires a temporary for either the argument a or the result off(a)to avoid undesired aliasing ofa`. ]

Ref 1:
C++03 12.8 Copying class objects [class.copy]
Para 12:

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

Alok Save
  • 202,538
  • 53
  • 430
  • 533