Constructor, destructor, and value assignment operator
Almost all classes have one or more constructors, one destructor, and one value assignment operator. This is not surprising, because they provide some of the most basic functions. The constructor controls the basic operations performed when an object is generated and ensures that the object is initialized. The Destructor destroys an object and ensures that it is completely cleared. The assignment operator gives the object a new value. Errors in these functions will bring endless negative effects to the entire class, so we must ensure its correctness. In this chapter, I will guide you how to use these functions to build the backbone of a well-structured class.
Clause 11: declare a copy constructor and a value assignment operator for classes requiring dynamic memory allocation
Let's look at the following class that represents a String object:
// A simple string class
Class string {
Public:
String (const char * value );
~ String ();
... // No copy constructor and operator =
PRIVATE:
Char * data;
};
String: string (const char * value)
{
If (value ){
Data = new char [strlen (value) + 1];
Strcpy (data, value );
}
Else {
Data = new char [1];
* Data = '/0 ';
}
}
Inline string ::~ String () {Delete [] data ;}
Note that the assignment operator and copy constructor are not declared in this class. This will cause some adverse consequences.
If two objects are defined as follows:
String A ("hello ");
String B ("world ");
The result is as follows:
A: Data --> "Hello/0"
B: Data --> "World/0"
Object A is a pointer to the memory containing the string "hello", and object B is a pointer to the memory containing the string "world. If the following values are assigned:
B =;
Because no custom operator = can be called, C ++ will generate and call a default operator = Operator (see clause 45 ). The default value assignment operator will assign values one by one from members of a to members of B. For pointers (A. Data and B. Data), it is a one-by-one copy. The assignment result is as follows:
A: Data --------> "Hello/0"
/
B: Data --/"World/0"
In this case, there are at least two problems. First, the memory that B once pointed to will never be deleted, so it will be lost forever. This is a typical example of Memory leakage. Second, now the pointers in A and B point to the same string, as long as one of them leaves its living space, the Destructor will delete the memory that another pointer points.
String A ("hello"); // defines and constructs
{// Create a new living space
String B ("world"); // defines and constructs B
...
B = A; // execute operator =,
// Lost B's memory
} // Exit the living space and call
// Destructor of B
String c = A; // The value of C. data cannot be determined!
// A. Data has been deleted
In this example, the last statement calls the copy constructor because it is not defined in the class, c ++ generates a copy constructor in the same way as processing the value assignment operator and performs the same action: one-by-one copy of the pointer in the object. This causes the same problem, but there is no need to worry about memory leakage because the initialized object cannot point to any memory. For example, in the above Code, when C. Data is initialized with A. data value, there is no memory leakage, because C. Data does not point anywhere. However, if C is initialized by a, c. data and. data points to the same place, which will be deleted twice: once C is destroyed, and once a is destroyed.
The copying of constructors is different from the assignment operator. When the value is called, it may cause problems. Of course, as stated in Clause 22, the object is rarely called for passing values, but let's take a look at the following example:
Void donothing (string localstring ){}
String S = "the truth is out there ";
Donothing (s );
Everything seems to be normal. However, because the passed localstring is a value, it must be initialized from s through the (default) copy constructor. Therefore, localstring has a copy of the pointer within S. When donothing stops running, localstring leaves its living space and calls the destructor. The result will also be: S contains a pointer to the memory that has been deleted by localstring.
By the way, it is unpredictable to use Delete to delete a deleted pointer. So even if s is never used, it will also cause problems when it leaves its living space.
The solution to this type of pointer disorder is to write your own copy constructor and value assignment operator functions as long as there are pointers in the class. In these functions, you can copy the data structures pointed to so that each object has its own copy; or you can use a reference counting mechanism (see section m29) tracks the number of objects currently pointing to a data structure. The reference counting method is more complex, and it requires more work within the constructor and destructor, but in some (though not all) programs, it saves a lot of memory and increases the speed.
For some classes, it is very difficult to implement the copy constructor and the value assignment operator, especially when you are sure that the program will not do the copy and value assignment operations, implementing them will be a little less than worth the candle. The example that omitted the copy constructor and the value assignment operator mentioned above is a poor design. What should we do if it is impractical to implement them in reality? Simply put, follow the suggestions in these terms: You can declare these functions (declared as private members) rather than define (implement) them. This prevents someone from calling them and the compiler from generating them. For details about this playful trick, see section 27.
Pay attention to the string class used in these terms. In the constructor, the [] is used carefully when two new calls are called, although only a single object is needed in one place. As mentioned in Clause 5, the same form must be used for supporting the use of new and delete, so this is also done here. Always note that [] is used for Delete only when [] is used for the corresponding new.