|
กก |
Until now, in our programs, we have only had as much memory as we have requested in variable declarations, arrays and other objects that we included, having the size of all of them to be fixed before the execution of the program. But, what if we need a variable amount of memory that can only be determined during the program execution?, for example, in case that we need an user input to determine the necessary amount of space. The answer is dynamic memory, for which C++ integrates the operators new and delete.
Operators new and new[ ] pointer = new typeor pointer = new type [elements]The first expression is used to assign memory to contain one element of type. The second one is used to assign a block (an array) of elements of type. For example: int * bobby;in this case, the operating system has assigned space for 5 elements of type int in the heap and it has returned a pointer to its beginning that has been assigned to bobby. Therefore, now, bobby points to a valid block of memory with space for 5 int. You could ask what is the difference between declaring a normal array and assigning memory to a pointer as we have just done. The most important one is that the size of an array must be a constant value, which limits its size to what we decide at the moment of designing the program before its execution, whereas the dynamic memory allocation allows to assign memory during the execution of the program using any variable, constant or combination of both as size. The dynamic memory is generally managed by the operating system, and in the multitask interfaces can be shared between several applications, so there is a possibility that the memory exhausts. If this happens and the operating system cannot assign the memory that we request with the operator new, a null pointer will be returned. For that reason is recommendable to always verify if after a call to instruction new the returned pointer is null: int * bobby;
Operator delete. delete pointer;or delete [] pointer;The first expression should be used to delete memory alloccated for a single element, and the second one for memory allocated for multiple elements (arrays). In most compilers both expressions are equivalent and can be used without distinction, although indeed they are two different operators and so must be considered for operator overloading (section 4.2).
This simple example that memorizes numbers does not have a limited amount of numbers that can be introduced, thanks to that we request to the system as much space as it is necessary to store all the numbers that the user wishes to introduce. In manifold C++ standard libraries is included the definition of NULL in order to reference to null pointers. In case that this constant is not defined you can do it yourself by defining it to 0: #define NULL 0It is indifferent to put 0 or NULL when you check pointers, but the use of NULL with pointers is widely extended and its use is recommended for greater legibility. The reason is that it is very rare that a pointer is compared or set directly to a numerical literal constant and thus this action is symbolically masked.
Dynamic memory in ANSI-COperators new and delete are exclusive of C++ and they are not available in C language. In C language, for assigning dynamic memory they are normally used some functions defined in the library stdlib.h. We are going to see them, since they are also valid in C++ and they are used in many existent programs.
The function malloc void * malloc (size_t nbytes);where nbytes is the number of bytes that we wish to be assigned to the pointer. The function returns a pointer of type void*, reason why we will have to type cast to the type of the destination pointer, for example: char * ronny;This assigns to ronny a pointer to an usable block of 10 bytes. When we want to assign a block of data of a different type other than char (different from 1 byte) we must multiply the number of elements wished by the size of each element. Luckyly we have at our disposition the operator sizeof, that returns the size of a data type of a concrete datum. int * bobby;This piece of code assigns to bobby a pointer to a block of 5 integer numbers of type int, that can be equal to 2, 4, 8 bytes or more according to the system where the program is compiled.
The function calloc. void * calloc (size_t nelements, size_t size);since it admits 2 parameters instead of one. These two parameters are multiplied to obtain the total size of the memory block to be assigned. Usually the first parameter (nelements) is the number of elements and the second one (size) serves to specify the size of each element. For example, we could define bobby with calloc thus: int * bobby;Another difference between malloc and calloc is that calloc initializates all its elements to 0.
The function realloc. void * realloc (void * pointer, size_t size);pointer parameter receives a pointer in which it has already been assigned a block of memory or a null pointer and size specifies the new size that the memory block must have. The function assigns size bytes of memory to the pointer. The function may need to change the location of the memory block for that the new size can fit, in that case the present content of the block is copied to the new one to guarantee that the existing data is not lost. The new pointer is returned by the function. If it has not been posible to assign the memory block with the new size it returns a null pointer but the pointer specified as parameter and its content remain unchanged.
The function free. void free (void * pointer);This function must only be used to release memory assigned with functions malloc, calloc and realloc.
| ||||||||||||