I recently made a small project and had a new understanding of C ++. It is not surprising that C ++ is too powerful to comprehend her meaning overnight.
First, we need to know why we need to reload new, and delete? This is not because of pointers. Actually, pointers are something that people like. They are so easy to use. However, we can avoid Memory leakage in small programs, and it is not so easy for large programs. However, we have a particularly good way to track our new and Delete actions and find unreleased memory. What is the solution? Microsoft provides us with a good method, that is, reload new, and delete.
Before implementation, we need to understand the working mechanism of new and delete. What a learning opportunity is this!
Like the new operator, sizeof is actually a built-in C ++ operator. However, strlen is not a function. There is no way to change the new feature. When we create an object, new does two things for us. 1. Apply for a sufficient memory space for storing objects, for a new array object, the compiler calculates the total space and then executes functions similar to the malloc function in C language. 2. Initialize an object. For a single object, including basic objects and class objects, you can use parentheses for initialization, such as int * Pn = new int (3 ); A * pA = new A (3); however, arrays cannot be initialized. For Class objects, you must define constructors without parameters. We cannot change the basic functions of new.
What we can change is how to allocate memory to objects. We can reload this function to allocate memory. Generally, the following overload methods are used:
Void * operator new (size_t size );
However, this is enough. In the general operator new overload function, we can add other parameters, but the first parameter must be of the size_t type, that is, the unsigned integer. This feature makes it possible for us to track memory application and release.
The specific implementation is the first operator new overload function. Our first function is like this:
Void * operator new (unsigned int size, const char * file, int line)
{
Cout <"New Size:" <size <Endl;
Cout <file <"" <line <Endl;
Void * P = malloc (size );
Return P;
}
Then replace all new with macros:
# Define new (_ file __, _ line __)
In this way, each time we call new, such as int * Pn = new int; the compiler replaces it with int * Pn = new (_ file __, _ line _) int, so we can call operator new, which is really amazing. It should be noted that the array is also applicable, but after compilation, the compiler calculates the required length and calls the operator new function we define.
For Delete, we do not need to use macro definitions. We only need to overload operator Delete. However, we need to overload two delete:
Void operator Delete (void * P)
{
Cout <"delete" <(INT) P <Endl;
Free (P );
}
Void operator Delete [] (void * P)
{
Cout <"Delete []" <(INT) P <Endl;
Free (P );
}
In fact, the content of the next function is the same as that of the previous function, but we must define it to support the release of arrays. So we just need a simple free (p) compiler to know whether the array we released is a single object, so we don't have to worry about it, we only need to provide the free function with a first address for applying for memory. Because when we apply for malloc, we also change the number assembly to the memory size.
From this we can draw the following conclusion: the space where int * Pn = new int [100]; is released using Delete Pn and delete [] Pn has the same effect. However, since the two methods are the same, what should we do with Delete []? In fact, delete [] has another role in releasing arrays of class objects, the compiler interprets Delete [] as calling the object's destructor, which is implemented through loops and finally releases the applied memory.
Now that we have tracked new and delete, we can easily determine whether the applied memory is finally released. to complete this process, we also need a linked list or other, when we apply for a piece of memory and add it to the linked list to release a piece of space, we can delete the node with the same address as the first address of the memory from the linked list, the ideal situation is that the linked list is empty. If it is not empty, it indicates Memory leakage (memory leaks.
Complete code:
# Include "malloc. H"
# Include "iostream. H"
# Ifdef _ debug
Void * operator new (unsigned int size, const char * file, int line)
{
Cout <"New Size:" <size <Endl;
Cout <file <"" <line <Endl;
// The following two methods can achieve the same effect, but the following one is better.
// Because the following method can be used to keep the original application method the same
// Void * P = malloc (size );
Void * P = Operator new (size );
Return P;
}
Void operator Delete (void * P)
{
Cout <"delete" <(INT) P <Endl;
Free (P );
}
Void operator Delete [] (void * P)
{
Cout <"Delete []" <(INT) P <Endl;
Free (P );
}
Void operator Delete (void * P, const char * file, int line)
{
Cout <"delete file line" <Endl;
Free (P );
}
Void operator Delete [] (void * P, const char * file, int line)
{
Cout <"Delete [] file line" <Endl;
Free (P );
}
# Define new (_ file __, _ line __)
# Endif
Void main ()
{
Int * P = new int [5];
Delete [] P;
// Delete P;
}
From http://blog.sina.com.cn/s/blog_3f56d7800100i1uf.html