In the below example code, regardless of it is a POD, class A has a copy constructor and also the assignment operator is overloaded.
foos and bars 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;
}