Why is it illegal to copy an object if a class member is a reference?

I met a quiz saying that the code on line 18 below is poorly formed because "it is poorly formed to use the implicitly assigned assignment operator when one of the members to be copied is a link."

I could not understand this. Why can't the link be copied? Why is line 16 legal? Line 16 is very similar to line 18, the copy constructor still needs to make a 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 } 
+5
source share
3 answers

Since in C++ forbidden to reassign the link.

 int &a = some_int; a = some_other_int; // value copied not reference a = some_int; // value copied not reference 

When you use the assignment operator (generated by the compiler), it blindly copies objects and thus tries to reassign your reference and is therefore invalid.

When you say a2 = a1; , the compiler will try to reassign a1.r to a2.r , which will lead to a compile-time failure, because this is bad behavior.

You can imagine the link as automatically dereferenced constant pointer . Thus, the string a2 = a1; will remain poorly formatted for the same reason as for the class below.

 struct A { A(int *var) : p(var) {} int * const p; }; 
+1
source

Line 16 uses the copy constructor, line 18 uses the assignment operator= . Two different functions with different restrictions.

Since the link cannot be restored, the compiler cannot generate an implicit assignment operator that makes any sense. Thus, he refuses to do this and generates an error.

The copy constructor generates the object for the first time, so it can link this link in the same way as in your own constructor.

+6
source

A class with a reference element does not have copy / move operators assigned by default. Links cannot bounce to another variable after the binding is established. In short, the copy constructor does this initial creation, while the default assignment operator will try to change it after binding.

Thus, the standard causes this case both for default copy operations and for transfer.

C ++ 11 Β§ 12.8p23

The default assignment operator for copy / move by default for class X is defined as remote if X has:

  • a variant member with a nontrivial corresponding assignment operator, and X a class similar to a union, or
  • non-static data member of type const non-class (or its array) or
  • non-static data element of reference type or
  • a non-static data member of class M (or its array) that cannot be copied / moved because overload resolution (13.3), applicable to the corresponding assignment operator Ms, leads to ambiguity or a function that is removed or inaccessible from the default assignment operator, or
  • a direct or virtual base class B that cannot be copied / transferred because overload resolution (13.3) applied to the assignment operator Bs results in an ambiguity or function that is removed or inaccessible from the default assignment operator or
  • for a redirection assignment operator, a non-static data element, or a direct base class with a type that does not have a move assignment operator and is not trivially copied, or any direct or indirect virtual base class.

You can, of course, 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; } 

Exit

 43,43 

But this will not (and cannot) restore the link. The overload presented here modifies the reference data; not the links themselves. This distinction is important.

Hope this helps.

+3
source

Source: https://habr.com/ru/post/1210440/


All Articles