cplusplus:pointers_4_slides
Pointers 4 slides
Dynamic memory, memory management, pointers as return types.1)
Mithat Konar
October 23, 2021
Dynamic memory allocation
- Dynamic memory allocation allows you to reserve blocks of computer memory at runtime.
- Typically used with pointers.
The new operator
new <data-type>
- reserves a block of memory to hold the specified <data-type>
- returns the base address of that block.
- optional parenthesis around
<data-type>
double *foo; // pointer to a double foo = new double; // allocate an unnamed block of memory // large enough to hold a double // and set foo to point to it.
foo
points to adouble
that isn't associated with a variable identifier.
Example
- simple-allocation.cpp
/** Dynamically allocate and use two doubles. */ #include <iostream> using namespace std; int main() { double *myPtr, *yourPtr; myPtr = new double; yourPtr = new double; cout << "Enter a number: "; cin >> *myPtr; cout << "Enter a number: "; cin >> *yourPtr; cout << "The average of the two numbers is " << (*myPtr + *yourPtr)/2.0 << "." << endl; return 0; }
Dynamic allocation of arrays
- Dynamic memory allocation can be used to allocate an array.
- Warning: If there is not enough memory available to allocate the desired block, BadThings™ will happen.
- dynamic-array.cpp
/** Dynamically allocate and use an array. */ #include <iostream> using namespace std; int main() { const int SIZE = 10; double *arrayPtr = new double[SIZE]; // create block to hold array /* You can use subscript notation [] to access an array: */ for(int i = 0; i < SIZE; i++) { arrayPtr[i] = i * i; } /* or pointer arithmetic: */ for(int i = 0; i < SIZE; i++) { cout << *(arrayPtr + i) << endl; } return 0; }
Memory Management
Memory management of regular variables
- The management of memory associated with regular local variables is automatic.
- Regular local variables are destroyed when the lifetime of the scope where they are declared ends.
- local-var-memory.cpp
/** Example showing local variable lifetime. */ #include <iostream> using namespace std; void ninetynine(); int main() { ninetynine(); // ... do some other stuff ... // return 0; } void ninetynine() { int localVar = 99; // localVar is destroyed at end of fcn call cout << localVar << endl; }
Memory management of dynamically allocated storage
- Dynamically allocated memory is not automatically managed.
- Below, the variable
localPtr
is destroyed at the end of the function call, but the dynamically allocated storage for theint
pointed to bylocalPtr
is not.
- memory-loss.cpp
/** Example showing lifetime of dynamically allocated storage and a * a small memory leak. */ #include <iostream> using namespace std; void ninetynine(); int main() { ninetynine(); // ... do some other stuff ... // return 0; } void ninetynine() { int *localPtr = nullptr; // localPtr is destroyed at end of fcn call localPtr = new int; // but not dynamically allocated storage *localPtr = 99; cout << *localPtr << endl; }
Memory leaks
- The previous is an example of a small memory leak.
- A bigger leak:
- memory-leak.cpp
/** Example of a sizable memory leak. */ #include <iostream> using namespace std; void ninetynine(); int main() { for (int i=0; i<10000; i++) { ninetynine(); } // ... do some other stuff ... // return 0; } void ninetynine() { int *localPtr = new int; *localPtr = 99; cout << *localPtr << endl; }
Memory leaks
- Memory leaks, no matter how small, are bad programming practice.
- Can be fixed by the proper use of deallocation: releasing back to the OS storage that was previously dynamically allocated.
- Deallocation of dynamically allocated storage does not happen automatically.
- You must explicitly (i.e., manually) deallocate the memory.
The delete operator
- The
delete
operator lets you explicitly deallocate memory that has been dynamically allocated.
int *myPtr = new int; ... delete myPtr; // deallocates block pointed to by myPtr.
- Principle: All dynamically allocated memory must be deallocated somewhere in the program.
- “For every
new
adelete
.”
Example
The code below fixes the memory leak introduced above:
- deallocation.cpp
/** Example showing deallocation. */ #include <iostream> using namespace std; void ninetynine(); int main() { ninetynine(); return 0; } void ninetynine() { int *localPtr = new int; *localPtr = 99; cout << *localPtr << endl; delete localPtr; // deallocates block pointed to by localPtr. }
Deallocating arrays
Use square brackets to deallocate dynamically allocated arrays: delete [] arrayPtr;
- Gaddis-Pr9-14.cpp
// This program totals and averages the sales figures for any // number of days. The figures are stored in a dynamically // allocated array. #include <iostream> #include <iomanip> using namespace std; int main() { double *sales = nullptr, // To dynamically allocate an array total = 0.0, // Accumulator average; // To hold average sales int numDays, // To hold the number of days of sales count; // Counter variable // Get the number of days of sales. cout << "How many days of sales figures do you wish "; cout << "to process? "; cin >> numDays; // Dynamically allocate an array large enough to hold // that many days of sales amounts. sales = new double[numDays]; // Get the sales figures for each day. cout << "Enter the sales figures below.\n"; for (count = 0; count < numDays; count++) { cout << "Day " << (count + 1) << ": "; cin >> sales[count]; } // Calculate the total sales for (count = 0; count < numDays; count++) { total += sales[count]; } // Calculate the average sales per day average = total / numDays; // Display the results cout << fixed << showpoint << setprecision(2); cout << "\n\nTotal Sales: $" << total << endl; cout << "Average Sales: $" << average << endl; // Free dynamically allocated memory delete [] sales; sales = nullptr; // Make sales a nullptr. return 0; }
heap vs. stack
- Local variables and dynamically allocated storage come from pools of RAM.
- stack: a pool of memory whose allocation and deallocation is automatically managed.
- Local and global variables are allocated from the stack.
- heap: a pool of memory whose allocation and deallocation is explicitly managed.
- Dynamically allocated storage is allocated from the heap.
- A more detailed discussion of the heap versus the stack, while important, is beyond the scope of present discussion.
''malloc'' and ''free''
malloc
andfree
can also used be used to allocate and deallocate storage.- Part of C and so are available in C++ as well.
- More cumbersome than
new
anddelete
, so their use is discouraged.
Returning Pointers from Functions
A function can return a pointer:
- returned-pointer.cpp
/** Returning a pointer from a function. */ #include <iostream> using namespace std; char* someChar(); int main() { char *foo; foo = someChar(); cout << *foo << endl; return 0; } char* someChar() { char *myCharPtr = new char; *myCharPtr = 'a'; return myCharPtr; }
Returning Pointers from Functions
- Do not return a pointer to a local variable in a function—because that local variable will cease to exist after the function terminates.
- Only return a pointer to:
- data that was passed to the function as an argument
- dynamically allocated memory
nullptr
.
Example
- Gaddis-Pr9-15.cpp
// This program demonstrates a function that returns // a pointer. #include <iostream> #include <cstdlib> // For rand and srand #include <ctime> // For the time function using namespace std; // Function prototype int *getRandomNumbers(int); int main() { int *numbers; // To point to the numbers // Get an array of five random numbers. numbers = getRandomNumbers(5); // Display the numbers. for (int count = 0; count < 5; count++) cout << numbers[count] << endl; // Free the memory. delete [] numbers; numbers = 0; return 0; } //************************************************** // The getRandomNumbers function returns a pointer * // to an array of random integers. The parameter * // indicates the number of numbers requested. * //************************************************** int *getRandomNumbers(int num) { int *arr = nullptr; // Array to hold the numbers // Return null if num is zero or negative. if (num <= 0) return NULL; // Dynamically allocate the array. arr = new int[num]; // Seed the random number generator by passing // the return value of time(0) to srand. srand( time(0) ); // Populate the array with random numbers. for (int count = 0; count < num; count++) arr[count] = rand(); // Return a pointer to the array. return arr; }
Smart Pointers
- C++11's smart pointers manage their own memory to help mitigate memory leaks.
- You need to
#include <memory>
. - One smart pointer is the
unique_ptr
:
unique_ptr<type_pointed_to> pointer_name( expression_to_allocate_memory )
Example
ptr
will be automatically deleted when the function returns.
- Gaddis-Pr9-17.cpp
// This program demonstrates a unique_ptr. #include <iostream> #include <memory> using namespace std; int main() { // Define a unique_ptr smart pointer, pointing // to a dynamically allocated int. unique_ptr<int> ptr( new int ); // Assign 99 to the dynamically allocated int. *ptr = 99; // Display the value of the dynamically allocated int. cout << *ptr << endl; return 0; }
Example
Dynamically allocating a large block of managed memory.
- Gaddis-Pr9-18.cpp
// This program demonstrates a unique_ptr pointing // to a dynamically allocated array of integers. #include <iostream> #include <memory> using namespace std; int main() { int max; // Max size of the array // Get the number of values to store. cout << "How many numbers do you want to enter? "; cin >> max; // Define a unique_ptr smart pointer, pointing // to a dynamically allocated array of ints. unique_ptr<int[]> ptr( new int[max]); // Get values for the array. for (int index = 0; index < max; index++) { cout << "Enter an integer number: "; cin >> ptr[index]; } // Display the values in the array. cout << "Here are the values you entered:\n"; for (int index = 0; index < max; index++) cout << ptr[index] << endl; return 0; }
Other smart pointers
- Other smart pointers are
weak_ptr
andshared_ptr
. - Not covered here.
1)
Portions adapted from:
Gaddis, Tony. “Pointers.” In Starting Out with C++: From Control Structures through Objects. 8th ed. Boston: Pearson, 2015. 495-546.
cplusplus/pointers_4_slides.txt · Last modified: 2021/10/24 03:02 by mithat