Reputation: 31
This is what I did originally.
class A
{ public:
A() { std::cout << "\ndefault constructor"; }
A(const A&) { std::cout << "\ncopy constructor"; }
A(int) { std::cout << "\nconversion constructor"; }
};
A a0; // print default constructor
A a1(a0); // print copy constructor note : direct initialization
A a2 = a0; // print copy constructor note : copy initialization
A a3(123); // print conversion constructor note : direct initialization
A a4 = 123; // print conversion constructor note : copy initialization (create a temp object from int)
However, if class A is slightly modified as the following (remove const in copy constructor), why are there compile error for the final line? thank you
class A
{ public:
A() { std::cout << "\ndefault constructor"; }
A(A&) { std::cout << "\ncopy constructor"; }
A(int) { std::cout << "\nconversion constructor"; }
};
A a0; // print default constructor
A a1(a0); // print copy constructor note : direct initialization
A a2 = a0; // print copy constructor note : copy initialization
A a3(123); // print conversion constructor note : direct initialization
//A a4 = 123; // compile error
Upvotes: 3
Views: 1224
Reputation: 132
For the case A a4 = 123;
, when object “a4” is being constructed, the statement
A a4 = 123;
is broken down by the compiler as
A a4 = A(123);
In above statement, one argument constructor i.e. A(int)
is used to convert integer value “123” to a temporary object & that temporary object is copied to the object “a4” using copy constructor. C++ does not allow to pass temporary objects by non-const reference because temporary objects are rvalue that can't be bound to reference to non-const.
So, generically, If you're not passing your argument with a const qualifier, then you can't create copies of const objects.
One more similar example for better understanding:
class Test
{
/* Class data members */
public:
Test(Test &t) { /* Copy data members from t*/}
Test() { /* Initialize data members */ }
};
Test fun()
{
cout << "fun() Called\n";
Test t;
return t;
}
int main()
{
Test t1;
Test t2 = fun(); //compilation error with non-const copy constructor
return 0;
}
$g++ -o main *.cpp
main.cpp: In function ‘int main()’:
main.cpp:22:18: error: cannot bind non-const lvalue reference of type ‘Test&’ to an rvalue of type ‘Test’
Test t2 = fun();
~~~^~
main.cpp:8:4: note: initializing argument 1 of ‘Test::Test(Test&)’
Test(Test &t) { /* Copy data members from t*/}
^~~~
Upvotes: 2
Reputation: 206567
A a4 = 123;
is equivalent to
A a4 = A(123); // The RHS is a temporary A object.
That works for the first case since there is a constructor that takes a A const&
as the argument type.
That does not work if the argument type is A&
. A temporary object can be used when the argument type is A const&
, not when it is A&
.
Upvotes: 6