When we design a class and assign a class object to another class object, we have three choices:
1. Do nothing, implement default behavior
2. Provide a explicit copy assignment operator
3. Explicitly refuse to assign a class object to another class object.
If you choose to three points, you only need to declare copy assignment operator as private and not provide its definition (C++11 standard can make copy assignment operator = delete) so that we can not be in any field (except member functions and friends, of course). Once a member function or friend attempts to affect a copy, the program fails at the link.
This session is primarily to verify the semantics of copy assignment and how they are molded, and we use point class to discuss:
class point{public: Point (float0.0float0.0); // No virtual function protected : float _x, _y;};
There is no reason to prohibit copying a point object. The question then becomes: is the default behavior sufficient? If we are only going to support a simple copy operation, then the default behavior is not only sufficient, but also efficient.
We need to design a copy assignment operator ourselves only if the default behavior is not secure enough or is not correct enough. What, is the default memberwise copy behavior not secure enough? Isn't it correct? Oh, no. Because of the values within the coordinates, no aliasing (aliasing) or memory leaks (leak) occur. If we provide a copy assignment operator ourselves, the program will run slower.
So we do not supply a copy assignment operator to point, and just rely on the default memberwise copy, does the compiler produce an entity? The answer is the same as copy constructor: not really! Because this class already has the bitwise copy semantics, implicit copy assignment operator is considered trivial and therefore will not be synthesized.
A class for the default copy assignment operator does not show bitwise copy semantics in the following cases:
1. When a class has a member object, and its class has a copy assignment operator.
2. When a class base class has a copy assignment operator.
3. When a class declares any virtual functions (at this time the vptr address of the class object at the right end of the non-copy, as it may be a derived class object).
4. When class inherits a virtual base class (regardless of whether the base class has copy operator).
C + + Standard said that copy assignment operator does not mean bitwise copy semantics is nontrivial, in fact, only nontrivial instances will be synthesized.
So, for our point class, this assignment operation:
= b;
Completed by bitwise copy, copy point B to point A, no copy assignment operator is called. In terms of semantics or efficiency, this is what we need. Note that we may still provide a copy constructor for the name Return Vlaue (NRV) optimization to open. The appearance of copy constructor should not make us think that we must also provide a copy assignment operator.
Now I import a copy assignment operator to illustrate the behavior of the operator under inheritance:
Inlinepoint&Point ::operator=(ConstPoint &Q) {_x=p._x; _y=p._y; return* This;}//now derive a Point3D class//Note is virtual inheritanceclassPoint3D:Virtual Publicpoint{ Public: Point3D (floatx =0.0,floaty =0.0,floatz =0.0); //...protected: float_z;};
If we do not define a copy assignment operator for Point3D, the compiler must synthesize one (because of the previous second and fourth reasons):
// possible synthesis Results inline point3d&Point3D::operatorConstthisconst Point3D &P) { this->point::operator=(p); // memberwise Copy the derived class members _z = p._z; return *this;}
Copy assignment operator has a non-orthogonal situation, which is the lack of a member assignment list. So we are not able to write:
// Inline point3d& Point3D not supported ::operator= (const Point3D &p3d) : Point (P3d), Z (p3d._z) {}
We must call the following two forms in order to call the base class copy assignment Operato
Point::operator= (p3d);
Or
(* (point*)this) = P3d;
Missing copy assignment list may seem like a trivial matter, but without it, the compiler generally has no way to suppress a copy operators of the previous base class being called. For example, the following is also the Vertex copy operator for virtual inheritance point:
// class vertex:virtrualpublic point inline vertex&Vertex::operator= (const Vertex &v) { this->point::operator=(v); = V._next; return *this;}
Now we derive vertex3d from Point3D and Vertex, and here is Vertex3d copy assignment operator:
Inline vertex3d&vertex3d::operator= (const Vertex3d &v) { this ->point::operator=(v); This->point3d::operator=(v); This->vertex::operator=(v); // ...}
How does the compiler suppress the copy assignment operator of point in the copy assignment operator of Point3D and Vertex? The compiler cannot repeat the traditional constructor solution (additional additional parameters) because, unlike constructor and destructor, the operation to take copy assignment operator addresses is legal. The following is a valid code:
typedef point3d& (Point3D::* Pmfpoint3d) (const point3d&= &point3d::operator= ;(x. *PMF) (x);
However, we cannot support it, and we still need to insert any possible number of parameters to copy assignment operator according to its unique inheritance system. This is also proven problematic when we support the configuration of arrays that are composed of class objects (virtual base clases).
Another approach is that the compiler might generate a differentiation function (split functions) for copy assignment operator to support this class as a most-derived class or as the middle base class. If copy assignment operator is generated by the compiler, then the Split function solution can be said to be well-defined, but if it is done by the designer of the class, it cannot be defined explicitly. For example, how does one differentiate a function like the following?
// Init_bases () is virtual inline Veretx3d&vertex3d:: operator = ( Span style= "color: #0000ff;" >const vertex3d &v) {init_bases (v);}
In fact, copy assignment operator behaves poorly in the case of virtual inheritance and requires careful design and explanation. Many compilers do not even attempt to get the correct semantics, they call each in the copy assignment operator of each middle base class instance, resulting in the invocation of multiple entities of virtual base class copy assignment operator. So many compilers are now, what about you? What does c+ standard say?
C + + standard also does not specify whether the subobject that represent the virtual base class should be assigned by implicit defined's copy assignment operator (assignment, assign) Content more than once.
If you solve this problem at the language level, you should provide an additional member copy list for copy assignment operator. Simply put, any solution that is based on program operation will result in high complexity and a large error dump To. Generally accepted, this is a major weakness of language, but also a place where a person should be careful to examine their program code (when he uses virtual base ckasses).
There is a way to ensure that the Most-deirved class will trigger the copy behavior of the virtual base class Subobject, which is the copy assignment Operato in derived class. At the end of the R function entity, explicitly call that operator, like this:
inline Vertex3d&vertex3d:: operator = (const vertexd &v) { this ->point3d::operator = (v); this ->vertex::operator =< Span style= "color: #000000;" > (v); // must place this if your cpmlier does
// not Suppress intermediate invcations this ->point:operator = (v); ...}
It is not possible to omit multiple copies of Subobject, but it is guaranteed to be semantically correct. Another solution is to copy virtual subobject into a separate function and invoke it conditionally based on call path.
However, it is recommended that you do not allow a copy operation of the virtual base class as much as possible. There is even a more outrageous suggestion: Do not declare data in any virtual base class.
Object Replication semantics