Replication control-copy constructor and value assignment operator
Introduction:
When defining a new type, what happens when you need to explicitly or implicitly specify copying, assigning, and revoking objects of this type-copying constructors, value assignment operators, and destructor!
Copy constructor: Has a single parameter. This parameter (commonly used for const modification) is a reference to this type. When a new object is defined and initialized with an object of the same type, the copy constructor is explicitly used; when you pass an object of this type to a function or return an object of this type from a function, the copy constructor is implicitly used.
Destructor: As a complementary constructor, when an object out of scope or dynamically assigned objects are deleted, the Destructor is automatically applied.
Value assignment operator: Like constructors, the copy operator can be overloaded by specifying different types of right operands. The version with the right operand as the class type is special: if we do not write this version, the compiler will synthesize it for us.
[Careful mine]
Generally, the compiler is very refined for the copy constructors we synthesize-they only do the necessary work, but for classes, relying on the default definition can sometimes lead to disasters!
1. copy constructor
There is only one form parameter, and this form parameter is a reference to this type of object (commonly used const modifier). Such a constructor is called a copy constructor. Like the default constructor, the copy constructor can be implicitly called by the compiler. The copy constructor can be used:
1) Initialize an object explicitly or implicitly based on another object of the same type.
2) copy an object and pass it as a real parameter to a function.
3) copy an object when returning from the function.
4) initialize elements in the sequential container.
5) initialize array elements based on the element initialization list.
1. object definition form
For the class type, the initialization replication mode and the direct mode are different: the direct initialization directly calls the constructor that matches the real parameter, and the replication initialization mode always calls the replication constructor. [During replication initialization, create a temporary object using the specified constructor, and then copy the constructor to copy the temporary object to the object being created.]
// Understand the differences between the following statements: string null_book = "9-99999-999-9"; string dots (10, '.'); string empty_copy = string (); string empty_direct;
For a class object, you must specify a single real parameter or explicitly create a temporary object for replication!
The initialization replication mode is supported to be compatible with C usage. When the condition permits, the compiler can skip copying the constructor to directly create an object, but the compiler is not obligated to do so!
Normally, direct initialization and replication initialization are only at a low level. However, there are essential differences between types that do not support replication or use non-explicit it constructor:
Ifstream file1 ("filename"); // OK ifstream file2 = "filename"; // Error, because I/O type objects cannot copy Sales_item item = string ("9-99999-999-9 ");
2. return values of form participation
When the parameter is not of the reference type, the value of the real parameter will be copied. Similarly, when the return value is of the non-reference type, a copy of the median value in the return statement will be returned.
// When the form parameter/return value is of the class type, the copy constructor replicates the data. // However, the parameter of this function is referenced by const, so the string make_plural (size_t, const string &, const string &) is not copied &);
3. initialize container elements
// First use the string default constructor to create a temporary value to initialize svec // then use the copy constructor to copy the temporary value to each element vector of svec <string> svec (5 );
[Recommended]
As a general rule, unless you want to use the default initial values of container elements, a more effective way is to allocate an empty container and add the values of known elements to the container.
4. constructor and array elements
If no element Initialization is provided for an array of class types, each element is initialized using the default constructor. However, if you use the array initialization list enclosed by regular curly braces to provide an explicit element initialization type, you can use copy initialization to initialize each element. Create an element of the appropriate type based on the specified value, and then use the copy constructor to copy the value to the corresponding element:
Sales_item arrItem[] = {string("0-201-16487-6"), string("0-201-54848-6"), string("0-201-82470-6"), Sales_item() };
Merged copy constructor
The merging and copying constructor performs one-by-one (non-static) member initialization to initialize the new object as a copy of the original object!
The composite replication constructor directly copies the values of built-in type members. class members use the replication constructor of this class to copy the values. Copying an array member is an exception. Although arrays cannot be copied, if a class has an array member, the composite copy constructor will copy the array. When copying an array, the synthesis and replication constructor copies each element of the array.
The simplest conceptual model for member Initialization is to regard the composite replication constructor as a constructor. Each data member is initialized in the constructor initialization list.
class Sales_item{public: Sales_item(const Sales_item &);private: std::string isbn; int units_sold; double revenue;};Sales_item::Sales_item(const Sales_item &orig): isbn(orig.isbn),units_sold(orig.units_sold),revenue(orig.revenue) {}
Define your own copy constructor
Class Foo {public: Foo (); Foo (const Foo &); // copy constructor };
The shape parameter of the copy constructor is usually a const reference. Because the object is passed to the function and the returned object from the function, this constructor should not be set to explicit!
For many classes, the composite copy constructor only performs the necessary work. Classes that only contain Class Members or built-in type members (but not pointer type members) can be copied without explicitly defining the copy constructor.
However, some classes must control what happens when copying objects. Such a class often has a data member that is a pointer or a member that represents other resources allocated in the constructor, while other classes must do some specific work when creating new objects. In both cases, the replication constructor must be defined!
Generally, the most difficult part to define a replication constructor is to recognize the need to copy the constructor O ~. As long as you realize that you need to copy the constructor, it is very easy to define the constructor. The definition of the replication constructor is the same as that of other constructor:It has the same name as the class.,No return value,Yes(And should)Use the constructor initialization list to initialize the members of the newly created object,You can do any other necessary work in the function body..
// Exercise P410 13.4 class NoName {public: NoName (): pstring (new std: string), I (0), d (0) {} NoName (const NoName & temp): I (temp. i), d (temp. d) {pstring = new std: string; * pstring = * (temp. pstring) ;}private: std: string * pstring; int I; double d ;};
Prohibit Replication
Some Classes need to completely prohibit replication. For example, the iostream class does not allow replication. If you want to disable replication, it seems that you can omit the replication constructor. However, if you do not define the replication constructor, the compiler will synthesize one.
By declaring but not defining the private copy constructor, you can disable any attempts to copy class objects:The replication attempts used in the code will be recorded as errors during compilation, and the replication attempts in member functions and friends will cause errors during the link.Incorrect!
Most classes should define replication constructor and default constructor
Copying constructor and/or default constructor are not defined, which seriously limits the use of classes: copying class objects that cannot be copied can only be passed as references to functions or returned from functions, nor can they be used as elements of a container.
Generally, it is best to explicitly or implicitly define the default constructor and copy constructor. The default constructor is merged only when no other constructor exists. If a replication constructor is defined, the default constructor must also be defined.
Ii. assignment operators
Like the copy constructor, if the class does not define its own value assignment operator, the compiler will combine into one!
1. Introduction to overload assignment
Overload OperatorIs a number of functions, whose names are operator followed by the symbols of the defined operators. Therefore,By definingOperator =Functions,We can define the value assignment.. Like any other function, an operator function has a return value and a form parameter table.The parameter table must have the same number of parameters as the operator.(If the operator is a class member, it includes the implicit this parameter ). Value assignment is a binary operation. Therefore, the operator function has two parameters: the first parameter corresponds to the left operand, and the second parameter corresponds to the right operand.
Most operators can be defined as member functions or non-member functions.. When the operator is a member function, its first operand is implicitly bound to the this pointer. Some operators (including value assignment operators) must be members of their own classes. Because the value assignment must be a member of the class, this is bound to the pointer to the left operand. Therefore, the value assignment operator accepts a single parameter, and the parameter is an object of the same class type. The right operand is generally passed as a const reference.
The value assignment operator also returns a reference to the same class type.
class Sales_item{public: Sales_item &operator=(const Sales_item &);};
2. Merge assignment operators
Merge assignment operatorsAssign values to members one by one: each Member of the right operand object is assigned to the corresponding member of the left operand object. In addition to arrays, each member is assigned a value in the general method of its type. Assign values to each array element to an array. For example:
Sales_item &Sales_item::operator=(const Sales_item &rhs){ isbn = rhs.isbn; units_sold = rhs.units_sold; revenue = rhs.revenue; return *this;}
3. Copying and assigning values are often used together.
In fact, we should regard the copy constructor and the value assignment operator as a unit. If one of them is needed, we can almost certainly need another one!
// Exercise P412 13.9 NoName & NoName: operator = (const NoName & rhs) {if (pstring) {delete pstring;} pstring = new string (); * pstring = * (rhs. pstring); I = rhs. i; d = rhs. d; return * this ;}
// Exercise 13.10 class Employee {public: typedef unsigned int num_type; Employee (const std: string Name = "NoName"): name (Name), mark (count) {set ();} Employee (const Employee & rhs): name (rhs. name), mark (count) {set ();}~ Employee () {-- count;} Employee & operator = (const Employee & rhs) {name = rhs. name; return * this;} ostream & output (ostream & OS) {OS <"Name:" <name <"\ t \ tMark: "<mark <endl; return OS;} private: std: string name; num_type mark; static num_type count; void set () {++ count ;}}; employee: num_type Employee: count = 0;