“ To be, or not to be: that is the question. ” — William Shakespeare, Hamlet Object Construction and Destruction

Stephen P Levitt

School of Electrical and Information Engineering University of the Witwatersrand

2019 Outline

1 The Lifetime of Objects Automatic Dynamic Memory Management

2 Object Construction

3 Object Destruction

Copy construction and assignment will be discussed later in the course.

Object Construction and Destruction 1 / 14 Objects and Memory

Just as an object takes up physical space in the real world, its existence in a computer program requires space in memory. Creating an object results in memory being allocated Destroying an object releases memory

Object Construction and Destruction : The Lifetime of Objects 2 / 14 The Lifetime of Objects

There are three ways in which an object’s lifetime (and its associated memory) can be managed: 1 Automatically - local objects and variables live within a certain 2 Dynamically - using 3 Statically - using static

Object Construction and Destruction : The Lifetime of Objects 3 / 14 Automatic memory management: What is the scope of the following: a, x and 5? What will the output of this program be, and are there any problems with it? Draw some diagrams to aid your explanation.

1 int* function(int x) 2 { 3 cout << x++ << endl; 4 return &x; 5 } 6 7 8 int main() 9 { 10 int* a = function(5); 11 cout << "a: " << *a; 12 13 return 0; 14 }

Object Construction and Destruction : The Lifetime of Objects : Automatic Memory Management 4 / 14 Using new and delete to Create and Destroy Objects

new returns a pointer to the object; delete deletes the object pointed to Lifetime controlled by programmer Memory is allocated from the free store or heap The free store is a finite resource

Object Construction and Destruction : The Lifetime of Objects : Dynamic Memory Management 5 / 14 Controlling an Object’s Lifetime — Example

1 int main() 2 { 3 cout << "Create rectangle? "; 4 auto answer = ' '; 5 cin >> answer; 6 7 if (answer == 'y') 8 { 9 auto rect_ptr = new Rectangle{3,5}; 10 cout << "Base: " << rect_ptr->base() << endl; 11 delete rect_ptr; 12 rect_ptr = nullptr; 13 } 14 15 return 0; 16 }

Object Construction and Destruction : The Lifetime of Objects : Dynamic Memory Management 6 / 14 Controlling an Object’s Lifetime — A More Realistic Example

cout << "Which photo do you want to edit? "; auto photo_filename = string{}; cin >> photo_filename;

// read in the photo's header information auto [width, height, bits_per_pixel] = readPhotoFileHeader(photo_filename);

// allocate memory for the photo - we only know the size of // the photo at runtime so however we do it - it has to // involve a dynamic memory allocation //..

// manipulate photo and then free up the memory // ...

Object Construction and Destruction : The Lifetime of Objects : Dynamic Memory Management 7 / 14 Constructors

Applied automatically when creating objects of a class May be overloaded (i.e. multiple constructors can exist) Cannot return a value (has implications for reporting errors) Data members are constructed/initialised in the order that they are declared in the class definition — make sure the constructor doesn’t specify a different order All data members are default-initialised prior to the constructor’s body either explicitly or by their default constructor

Object Construction and Destruction : Object Construction 8 / 14 A Typical Constructor — Screen class’s Constructor

class Screen { public: // Screen's constructor Screen( string::size_type height = 40, string::size_type width = 8, char bkground = '#'); }

Screen::Screen(string::size_type height, string::size_type width, char bkground): height_{height}, width_{width}, cursor_{TOP_LEFT}, screen_(height * width, bkground) { /* nothing left to do */}

All the work is done in the member initialisation list. Object Construction and Destruction : Object Construction 9 / 14 The Default Constructor

Able to be invoked without supplying arguments — useful when there are sensible default values Automatically provided if no constructors are specified by the class designer Can be a user-provided constructor that has no parameters, or has default arguments for all parameters Once a class has any user-provided constructor, an object can only be created using that constructor

Object Construction and Destruction : Object Construction 10 / 14 The Default Constructor II

// no parameters Complex::Complex(): re_{0.0}, im_{0.0} {}

// defaults for all parameters Complex::Complex(double re = 0.0, double im = 0.0): re_{re}, im_{im} {} Prefer // compiler provides default ctor which uses in-class member initializers class Complex { ... private: double re_ = 0.0; double im_ = 0.0; } Object Construction and Destruction : Object Construction 11 / 14 The Default Constructor III

When other constructors are present:

class Complex { public: Complex() = default; // explicitly make default constructor available Complex(double re; double im); ...

private: double re_ = 0.0; double im_ = 0.0; }

Object Construction and Destruction : Object Construction 12 / 14 Calling the Default Constructor

// creates an object on the stack auto number = Complex{};

// creates an object on the heap auto number = new Complex{};

Object Construction and Destruction : Object Construction 13 / 14 The Class Destructor

Complement of the constructor Provided automatically if not provided by the class designer Invoked automatically when an object of the class goes out of scope or delete is used – do not call explicitly Usually used for freeing resources acquired during the construction or lifetime of the object Only a single destructor can be defined Cannot return a value or take parameters

Account::~Account() { // release any resources acquired }

Object Construction and Destruction : Object Destruction 14 / 14