I'm trying to relearn C++, and I tend to want to have an intricate understanding of how everything works (not just "how do I do this"). So I'm wondering why this produces the error it does. Yes, I know that an overloaded assignment operator is supposed to use references (and it works fine if I do), but I'm hoping that an answer to this question might help me learn more about the language rules.
class some_class {
public:
int n1;
some_class(int z) : n1(z) { }
some_class(some_class &x) : n1(x.n1) { }
some_class operator= (some_class x) { n1 = x.n1; return *this; }
// some_class & operator= (some_class & x) { n1 = x.n1; return *this; } works fine
};
main () {
some_class a(10);
some_class b(20);
some_class c(30);
c = b = a; // error here
}
The compiler (C++03) gives me this, on the c = b = a line:
In function 'int main()':
error: no matching function for call to 'some_class::some_class(some_class)'
note: candidates are: some_class::some_class(some_class&)
note: some_class::some_class(int)
error: initializing argument 1 of 'some_class some_class::operator=(some_class)'
It's confusing to me, because b = a works fine, and it's looking for a constructor that I'm not legally allowed to declare. I realize that in c = b = a, the b = a part returns a value (not a reference), and that may result in the result being copied to a temporary. But why would c = <temporary> result in a compilation error when b = a wouldn't? Any idea what's going on?
Your copy constructor has a non-const reference as its parameter. Temporaries can't be bound to non-const references. When you do:
c = b = a;
This is equivalent (as you say) to:
c.operator=(<temporary>);
It therefore tries to invoke your copy constructor with a temporary whilst initialising the first argument of the call to operator=. This fails for the reason mentioned. A sensible way to fix it is to change the signature of operator= to the more conventional:
some_class& operator=(const some_class& x);
The copy constructor would not then be needed in the implementation of operator=, since the argument to operator= would not be copied. However, copy constructors should generally take a const reference parameter, so you should also change the signature of the copy constructor to:
some_class(const some_class& x);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With