Author: winter
This is a common case: When you store data in a cache, you often need to adjust the cache size during runtime to accommodate more data. The traditional memory redistribution technology is cumbersome and prone to errors: in C language, realloc () is called every time the cache needs to be expanded (). Even worse in C ++, you cannot even re-apply for memory for the array allocated for the new operation in the function. Not only do you need to allocate data yourself, but you must also copy the data in the original cache to the new destination cache and then release the cache of the previous array. This article will provide a secure, simple, and automated C ++ memory redistribution technology to address this problem-that is, using STL vector.
It is safe, simple, and automatic to use STL vector objects instead of built-in arrays to save the obtained data.
Further Problem Analysis
Before proposing a solution, I would like to give a specific example to illustrate the disadvantages and complexity of C ++ re-allocating memory. Suppose you have a cataloguing application that reads the isbns entered by the user and inserts it into an array until the user inputs 0. If you insert more data than the array capacity, you must increase the size accordingly:
# Include <iostream>
Using namespace STD;
Int main ()
...{
Int size = 2; // the size of the initialization array; it is adjusted at runtime.
Int * P = new int [size];
Int ISBN;
For (INT n = 0; ++ N)
...{
Cout <"enter an ISBN; press 0 to stop ";
Cin> ISBN;
If (ISBN = 0)
Break;
If (n = size) // does the array reach the upper limit?
Reallocate (p, size );
P [N] = ISBN; // Insert elements into the expanded array
}
Delete [] P; // do not forget this step!
}
Note how tedious the process of inserting data into the array is. Check whether the cache reaches the upper limit for each iteration. If yes, the program calls the User-Defined Function reallocate (), which is implemented as follows:
# Include <algorithm> // for STD: Copy
Int reallocate (int * & P, Int & size)
...{
Size * = 2; // double the array's size with each reallocation
Int * temp = new int [size];
STD: Copy (p, p + (size/2), temp );
Delete [] P; // Release Original, smaller Buffer
P = temp; // reassign P to the newly allocated buffer
}
Reallocate () uses the stl std: Copy () algorithm to reasonably expand the cache-doubling each extension. This method can avoid allocating too much memory in advance and reduce the amount of memory to be re-allocated. This technology needs to be fully tested and debugged, especially when implemented by beginners. In addition, reallocate () is not universal and can only process integer arrays. It is powerless for other data types. You must define additional versions of the function or templated it. Fortunately, there is a more clever way to achieve it.
Create and optimize Vector
Each STL container has an allocator, which is a built-in memory manager that can automatically re-allocate the storage space of the container as needed. Therefore, the above program can be greatly simplified and get rid of the reallocator function.
Step 1: Create a vector
Replace the built-in array with a vector object to save the obtained data. In Main (), read ISBN cyclically and check whether it is 0. If it is not 0, insert the value to vector by calling the push_back () member function:
# Include <iostream>
# Include <vector>
Using namespace STD;
Int main ()
...{
Vector <int> VI;
Int ISBN;
While (true)
...{
Cout <"enter an ISBN; press 0 to stop ";
Cin> ISBN;
If (ISBN = 0)
Break;
Vi. push_back (ISBN); // insert element into vector
}
}
During the construction of a vector object, it first allocates a default cache size defined by its implementation. Generally, the initial data storage space allocated by the vector is 64-256 slots ). When the vector feels that there is not enough storage space, it will automatically allocate more memory. In fact, as long as you want, you can call push_back () for any number of times without even knowing where the allocation occurs.
To access Vector elements, use the overloaded [] operator. The following loop shows all vector elements on the screen:
For (INT n = 0; n <VI. Size (); ++ N)
...{
Cout <"ISBN:" <VI [N] <Endl;
}
Step 2: Optimization
In most cases, you should let the vector automatically manage its memory, as we did in the above program. However, it is also useful to rewrite the default allocation scheme in time-based tasks. Suppose we know in advance that the number of isbns is at least 2000. Then we can point out the capacity during Object Construction so that the vector has at least 2000 elements:
Vector <int> VI (2000); // The initial capacity is 2000 elements.
In addition, we can also call the resize () member function:
Vi. Resize (2000); // create a space of no less than 2000 Elements
In this way, the middle redistribution is avoided and the efficiency is improved.