I met a quiz saying that the code in line 18 below is ill-formed because "It is ill-formed to use an implicitly defined assignment operator when one of the members that will need to be copied is a reference. "
I couldn't understand that. Why reference could not be copied? Why Line 16 is legal? Line 16 is quite similar to line 18, a copy constructor still need to do the copy, right?
1 #include <iostream>
2
3 struct A
4 {
5 A(int& var) : r(var) {}
6
7 int &r;
8 };
9
10 int main(int argc, char** argv)
11 {
12 int x = 23;
13
14 A a1(x);
15
16 A a2 = a1;
17
18 a2 = a1;
19
20 return 0;
21 }
It is necessary to pass object as reference and not by value because if you pass it by value its copy is constructed using the copy constructor. This means the copy constructor would call itself to make copy. This process will go on until the compiler runs out of memory.
The point of "pass by reference" is to not make a copy as soon as Employee constructor is called, but only when you choose to initialize one of Employee's member with the Date passed.
C++ gives you the choice: use the assignment operator to copy the value (copy/value semantics), or use a pointer-copy to copy a pointer (reference semantics). C++ allows you to override the assignment operator to do anything your heart desires, however the default (and most common) choice is to copy the value.
The copy constructor and assignment operator just do different things where references are concerned. The copy constructor initializes the reference to point to the same object that the reference points to in the instance that is being copied; the assignment operator actually copies the value of the referenced object.
Line 16 uses a copy constructor, line 18 uses the assignment operator operator=
. Two different functions with different restrictions.
Because a reference can't be rebound, the compiler can't generate an implicit assignment operator that makes any sense. Thus it refuses to do so, and generates an error.
A copy constructor is generating the object for the first time, so it can bind that reference the same way you did in your own constructor.
A class with a reference member has no default-provided copy/move assignment operators. References cannot be rebound to reference a different variable once binding is established. In short, the copy constructor is making that initial establishment, while the default assignment operator would be trying to change it after-binding.
The standard therefore calls this case out for both default copy and move assignment operators.
C++11 § 12.8p23
A defaulted copy/move assignment operator for class X is defined as deleted if X has:
You can certainly write your own overload.
#include <iostream>
struct A
{
A(int& var) : r(var) {}
int &r;
A& operator=(const A& obj)
{
r = obj.r; // value copied, reference-binding remains the same
return *this;
}
};
int main(int argc, char** argv)
{
int x = 42;
int y = 43;
A a1(x);
A a2(y);
A a3 = a1; // legal. default copy-ctor invoked
a3 = a2; // legal. user-defined copy-assignment invoked
std::cout << x << ',' << y << '\n';
return 0;
}
Output
43,43
But this will not (and cannot) rebind the reference. The overload provided here changes the referenced data; not the references themselves. Such a distinction is important.
Hope this helps.
Because it is illegal in C++
to reassign to a reference.
int &a = some_int;
a = some_other_int; // value copied not reference
a = some_int; // value copied not reference
When you use assignation operator (generated by compiler), it blindly does the copy of objects and thus try to reassign to your reference and hence is invalid.
When you say a2 = a1;
, compiler would try to reassign a1.r
to a2.r
making it fail at compile time because it is ill-formation.
You can think of a reference as an automatically dereferenced constant pointer
. So the line a2 = a1;
will remain ill-formatted for the same reason as for the class below.
struct A
{
A(int *var) : p(var) {}
int * const p;
};
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