Effective C ++ 2e Item11

zhaozj2021-02-11  179

Constructor, destructor, and assignment operator

Almost all classes have one or more constructor, a destructor and an assignment operator. This is not surprising, because they are all the most basic functions. Construct the basic operation of the function control object generation, and ensure that the object is initialized; the destructive function destroys an object and guarantees that it is completely cleared; assigning the operator gives an object a new value. In these functions, an error will bring endless negative impact on the entire class, so be sure to ensure its correctness. This chapter will guide how to use these functions to build a good structure.

Terms 11: For a class declare a copy constructor and an assignment operator to dynamically allocate memory

Look at the class that represents the String object:

// A very 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 [strull 1]; struct (data, value);} else {data = new char [1]; * data = '/ 0';}}}}

Inline string :: ~ String () {delete [] data;}

Note that this class has no declaration operator and copy constructor. This will bring some adverse consequences.

If this is defined in two objects:

String a ("Hello"); String B ("World");

The result will be as follows:

A: Data -> "Hello / 0" B: Data -> "World / 0"

The interior of the object A is a pointer to memory containing a string "hello", and the internal object B is a pointer to memory containing a string "world". If the following assignment is performed:

B = a;

Because there is no custom operator = can be called, C will generate and call a default Operator = operator (see Terms 45). This default assignment operator executes the assignment operation of the members of the members from A to B, which is a bit copying of the pointer (A.DATA and B.DATA). The result of the assignment is as follows:

A: Data --------> "Hello / 0" / B: Data - / "World / 0"

There are at least two problems in this case. First, B-pointed memory will never be deleted, so it will be lost forever. This is a typical example of generating memory leakage. Second, now A and B pointers point to the same string, then as long as one of them leaves its living space, the destructive function deletes the block of the other pointer to point to.

String a ("Hello"); // Defines and construct a

{// Open a new survival String B ("world"); // Define and construct B

...

B = a; // Execute Operator =, // Lost B's memory

} // Leave the living space, call // b: String c = a; // c.data's value cannot be determined! // A.Data has been removed

The last statement in the example calls the copy constructor because it does not define a copy constructor in the class, and C generates a copy constructor in the same way as the processing assignment operator and performs the same action: the pointer to the object is bitten. . This will result in the same problem, but don't worry about memory leaks, because the object being initialized cannot point to any memory. For example, in the case of the code, there is no memory leak when C.DATA is initialized with A.DATA's value, as C.Data did not point anywhere. However, if C is initialized by A, C.Data and A.Data points to the same place, that place will be deleted twice: when C is destroyed at C, the other is destroyed in A.

The case and the assignment operator is a bit different from the copy constructor. It will generate a problem when the value is called. Of course, as explained in Terms 22, it is generally rarely transmitted value to the object, but still look at the example below:

Void Donothing (String localstring) {}

String s = "The truth is out there";

Donothing (s);

Everything is normal. However, because of the delivered localstring is a value, it must initialize from S by (default) copy constructor. The Localstring has a copy of a pointer in one s. When Donothing ends, localstring leaves its living space and calls the destructor. The result will also be: S contains a pointer to the memory that point to LOCALSTRING.

Incident, use Delete to delete a pointer that has been deleted, and the result is unpredictable. So even if S will never be used, it will also bring problems when it leaves its living space.

Solution to solve this type of pointer confusion problem is that as long as there is a pointer in the class, you must write your own version of the copy constructor and assignment operator function. In these functions, you can copy those data structures that are pointed out, so that each object has its own copy; or you can use some reference counting mechanism (see Terms M29) to track how many objects currently point to one data structure. The reference to the count is more complex, and it requires more work inside the constructor and the designer function, but in some (although not all) programs, it will save a lot of memory and effectively improve the speed.

For some classes, when the copy constructor and assignment operators are very troublesome, especially when it is confident that there is no copy and assignment operation in the program, it will be relatively unpaid. The exempted copy constructor and assignment operator, it is a bad design, and what should I do when I realize them unrealistic? Very simple, the recommendations of the article: You can only declare these functions (declare for Private members) without defining (implementation). This prevents someone from calling them, but also prevents the compiler from generating them. For details on this playful tip, see Terms 27.

转载请注明原文地址:https://www.9cbs.com/read-4464.html

New Post(0)