In the below example code, regardless of it is a POD, class A
has a copy constructor and also the assignment operator is overloaded.
foo
s and bar
s are entities of type A
. Depending on how foo
and bar
are constructed, the compiler gives error messages in some cases when I use the assignment operator in the main code. The error messages are commented in the snipped code below.
I understand that the problem is related to the implicit use of the assignment operator. But, why foo1=bar1;
is ok and foo2=bar2;
is not?
Edit : It is clear from the comments that compilers interpret A foo();
as a function declaration not a ctor. This explains why I got first and second error messages in my code. However, the reason for the error message on the line A foo4 = A(2,3);
is something different. It is related to the design of copy constructor and the object must be const
.
(See: Why C++ copy constructor must use const object? )
I corrected the copy constructor as follow,
A(const A &a) {x =a.x; y=a.y;}
Edit 2 : After
toby-speight 's comment, I recompiled the same code (having copy constructor without 'const' object viz. A(A &a) {x =a.x; y=a.y;}
) by using gcc compiler with c++17.
The error on the line A foo4 = A(2,3);
disappeared.This shows that guaranteed copy elision is implemented in gcc (at least in gcc 7.3.1, which is the version I have been using).
#include <iostream>
class A{
public:
int x;
int y;
A(): x(0),y(0) { }
A(int xval, int yval): x(xval),y(yval) { }
//Copy constructor.
A(A &a) {x =a.x; y=a.y; }
//Assgnment operator overloading
A& operator=(A &a){
if (this !=&a){
x=a.x;
y=a.y;
}
return *this;
}
};
int main(){
A foo1(2,3);
A bar1;
foo1 = bar1;
A foo2();
A bar2();
foo2 = bar2; // error: cannot convert ‘A()’ to ‘A()’ in assignment
A foo3(2,3);
A bar3();
foo3 = bar3; // error: no match for ‘operator=’ (operand types are ‘A’ and ‘A()’)
A foo4 = A(2,3); //<--- // error: cannot bind non-const lvalue reference of type ‘A&’ to an rvalue of type ‘A’
A bar4; //ok. // note: initializing argument 1 of ‘A::A(A&)’
foo4 = bar4;
return 0;
}