0
#include<iostream>
#include<string>

using namespace std;

class B;

class A {
    public:
        A(const A&) {   //copy ctor
            cout << "Copy ctor A\n";
        }
        A() {}  //default ctor
        A(const B&) {   //lets call this conversion ctor
            cout << "B to A conversion ctor\n";
        }
};

class B {
    public:

};

int main()
{
    B b;
    A a = b;
}

The above code prints B to A conversion ctor. But as per what I have discovered after looking around for a while, it should print

B to A conversion ctor
Copy ctor A

As first a temporary object of type A is created by conversion ctor and then that object is copied into a wherein copy ctor gets called. Also, when copy ctor is made private, statement A a = b; generates this error:

‘A::A(const A&)’ is private

which is obvious as to copy the temporary object into a copy ctor must be visible. So my question is why copy ctor is not being eventually called as evident from the output(please correct if am leading wrong somewhere here) even though it is required to be accessible?

stillanoob
  • 1,279
  • 2
  • 16
  • 29
  • if A is not initialized before, the expression `A a = b` interperted as `A a(b)` – David Haim Nov 24 '15 at 10:32
  • @DavidHaim that's not completely true. Copy-initialization and direct-initialization have different rules for what is and is not valid. – TartanLlama Nov 24 '15 at 10:35
  • @DavidHaim But its a kinda copy initialization and hence, copy ctor ought to be called – stillanoob Nov 24 '15 at 10:36
  • @DavidHaim it cannot be initialized before its definition statement anyway. – Ad N Nov 24 '15 at 10:37
  • See http://stackoverflow.com/a/32272606/1027706 for the answer has to why the copy ctor is (rightfully) not called, and why the it must be accessible even if it is not used. – Ad N Nov 24 '15 at 10:40

2 Answers2

2
A a = b;

This form is called copy-initialization. The applicable rule states that in this case a temporary A object will be constructed from the B instance and that temporary will then be used to direct-initialize a.

However, the compiler is allowed to elide the copy as it is not necessary. Even though the elision is allowed, the class still needs to be copyable for the form to be valid.

You can see the result without elision by passing -fno-elide-constructors to GCC or Clang.

Community
  • 1
  • 1
TartanLlama
  • 63,752
  • 13
  • 157
  • 193
0

why copy ctor is not being eventually called as evident from the output

According to the standard, an implementation is allowed to omit the copy/move construction in certain criteria. In this case, a temporary A(constructed from b, and will be copied to a) 's construction is omitted.

$12.8/31 Copying and moving class objects [class.copy]

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

And

(31.3) — when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same type (ignoring cv-qualification), the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move

songyuanyao
  • 169,198
  • 16
  • 310
  • 405