Show Lecture.DynamicMemory as a slide show.
In C, we used functions to allocate & free memory:
They still work, but don’t use them. They’re not type-safe, and they don’t call ctors & dtors (constructors and destructors).
In C++, we use keywords to allocate & free memory:
new
delete
new []
delete []
You have to delete the memory that you allocate.
Don’t delete it more than once!
int *p = new int; *p = 42; cout << p << ' ' << *p << '\n'; delete p;
0xcda2b0 42
int *a = new int[10]; for (int i=0; i<10; i++) a[i] = i*11; for (int i=0; i<10; i++) cout << a[i] << ','; delete[] a; // Note the []
0,11,22,33,44,55,66,77,88,99,
new
with delete
, and new []
with delete []
new
, you must call delete
.
new []
, you must call delete []
.
If you mix them up, the system might catch your error, or it might not.
Java programmers, remember that objects do not have to be dynamically allocated. You can, but you don’t have to.
string s = new string;
c.cc:1: error: conversion from 'std::__cxx11::string*' {aka 'std::__cxx11::basic_string<char>*'} to non-scalar type 'std::__cxx11::string' {aka 'std::__cxx11::basic_string<char>'} requested
Instead, just declare the string:
string s = "Hi there\n"; cout << s;
Hi there
Sure, the string allocates dynamic memory, internally, but that’s none of your business.
In general, use standard containers such as string, vector, or list when you can. They handle the dynamic memory allocation, so you don’t have to.
Besides, code that deals with dynamic memory is easy to get wrong.
Code that you write will have bugs. vector
, on the other hand,
has had its bugs discovered & fixed ages ago.
If you must use dynamic memory, then consider unique_ptr and shared_ptr.
Every call to new
must be matched by exactly one delete
.
Not zero, and not two. One.
Similarly, every call to new []
must be matched
by exactly one delete []
.
If you don’t call delete
, then the memory is forgotten.
We call this a memory leak.
Sure, the memory will be implicitly freed when the program ends. However, some programs run for a good long time before they end. This program allocates memory every second, and forgets to free it.
// Clock program draw_clock_face(); while (sleep(1)) { GraphicsContext *gc = new GraphicsContext; gc->redraw(); // forget to free GraphicsContext }
Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip. Drip.
What happens if you call delete
more than once?
float *p = new float[100]; delete[] p; delete[] p;
free(): double free detected in tcache 2 SIGABRT: Aborted
new
& delete
so that they detect a double delete
, and respond with a sensible
error message.