Dynamic memory, memory management, pointers as return types.
Mithat Konar
October 23, 2021
new <data-type>
<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 a double
that isn't associated with a variable identifier./** 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; }
/** 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; }
/** 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; }
localPtr
is destroyed at the end of the function call, but the dynamically allocated storage for the int
pointed to by localPtr
is not./** 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; }
/** 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; }
delete
operator lets you explicitly deallocate memory that has been dynamically allocated.int *myPtr = new int; ... delete myPtr; // deallocates block pointed to by myPtr.
new
a delete
.”The code below fixes the memory leak introduced above:
/** 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. }
Use square brackets to deallocate dynamically allocated arrays: delete [] arrayPtr;
// 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; }
malloc
and free
can also used be used to allocate and deallocate storage.new
and delete
, so their use is discouraged.A function can return a pointer:
/** 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; }
nullptr
.// 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; }
#include <memory>
.unique_ptr
:
unique_ptr<type_pointed_to> pointer_name( expression_to_allocate_memory )
ptr
will be automatically deleted when the function returns.
// 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; }
Dynamically allocating a large block of managed memory.
// 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; }
weak_ptr
and shared_ptr
.