Article 16: Paired use new and delete to take the same form
See what's wrong with the following code:
string* stringarray=new String[100];......delete string;
The program uses new to open up memory and then uses Delete to free up memory, seemingly without problems. But there is something completely wrong: The program has ambiguous behavior. The Stringarray contains 100 string objects, but delete deletes only one, and the remaining 99 are not deleted, and their destructors are not called.
When using new (that is, creating an object dynamically with new), there are two steps. The first step is to open up memory (by operator new, refer to clause 49, clause 51). In the second step, the constructor is called at the Open memory point. There are also two steps when using Delete, the first call to the destructor, and the second step to freeing the memory (via operator delete). Refer to here for details. When you use new, you specify how many objects are created, but when you use Delete, you do not specify how many objects are deleted (how many of the object's destructors are called).
The question can be a little simpler: the pointer being deleted, refers to a single object or an array. The memory layout of a single object is a single object, and the array has one more parameter: How many single objects (that is, the size of the array). Usually the previous byte of the array pointer (the first pointer, the pointer to the array header) holds the size of the array, as in the previous example: * (int *) stringArray-1) has a value of 100. When you use delete[], you get this value, and then you call delete after the head pointer.
So what happens if a non-array pointer calls delete[] on it? The results are undefined, but should not make you happy.
So it should be done according to the rules: if you use new to open up memory, use Delete to release. If you use new[] to open up memory, use delete[] to release.
The above rules are especially important when writing a class with pointers. Because the destructor has only one, the constructor can have multiple functions. Constructors can use new or new[] to initialize pointers, but destructors can only use one method to free delete/delete[].
This rule is also important for people who prefer to use TypeDef, because the TypeDef author should make it clear that when a programmer creates a TypeDef type object with new, it should be released using delete/delete[]. For example:
typedef string ADDRESSLINES[4];//has 4 rows, each line is a stringstring* pal=new addresslines;//here returns a string*, equivalent to new string[4]
So when you release it, it should be delete[], not the delete.
In order to avoid such errors, it is best to try not to use the array as a TypeDef action. In C + + STL There are string, vector and other templates (clause 54), you can reduce the array requirements to almost zero.
Article 17: Placing a Newed object into a smart pointer with a standalone statement
When using smart pointers, you should put the newly created object pointer in a smart pointer with a separate statement, or it might cause a memory leak. Take a look at the following example.
Suppose you have a function that handles a program, it has two parameters, one is a dynamically allocated widget, and the other is a priority.
int Processwidget (shared_ptr<widget> pw, int priority);
Now there's a function to get the priority
int priority ();
If call is required, this is called:
Processwidget (shared_prt<widget> (new Widget), priority ());
Although object management resources are used above, there may be resource leaks.
The compiler must first calculate the parameters that will be passed in before the output processwidget. The second parameter above is the call to the function priority (), and the first argument does have two parts, which is not the execution of the new widget expression, and the other part is the execution of the shared_ptr constructor. So there are three things to do before calling Processwidget:
1. Execute the priority () function
2. Execute New Widget
3. Execute shared_ptr Constructor
In what order does the C + + compiler accomplish these things? The elasticity is very big. In Java and C #, the calculation of such function parameters is always done in a specific order, but not necessarily in C + +. The only thing that can be determined is that the new widget was called before shared_ptr. But the function priority is not necessarily the first. Assuming the second, then the order is 1, execute the new Widget. 2, Executive function priority (). 3 executes the shared_ptr constructor.
If an exception occurs to the function priority () call, the pointer returned by the new widget has not yet been placed in the shared_ptr. This can cause a memory leak.
This is because an exception is sent between the creation of a resource (new Widget) and the placement of resources into a resource management object two operations. It's easy to avoid this: you'll create widgets and put widgets in a smart pointer two steps don't separate.
Shared_prt<widget> PW (new Widget);p Rocesswidget (Pw,priority ());
In the actions across statements, the compiler does not have permission to rearrange individual statements, so the above call does not send a memory leak.
"Effective C + +" Resource management: clause 16-clause 17