200 likes | 265 Views
Comp5421 Object Oriented Programming. Using C++ Efficiently Lecture 4 (2) Tianxiang Shen Summer 2002 Department of Computer Science Concordia university. C++ Storage Management. Dynamic memory management:
E N D
Comp5421 Object Oriented Programming Using C++ Efficiently Lecture 4 (2) Tianxiang Shen Summer 2002 Department of Computer Science Concordia university Concordia TAV 2002 Comp5421_42
C++ Storage Management • Dynamic memory management: • 1. For many applications, memory requirements are given only at run time, thus the memory should be allocated when the demand is given rather than preallocated during the compilation process. The dynamic memory management is used for these memory requirements. • 2. Heap: When a Program is loaded into memory, the system sets aside a block of memory, called the heap, that is available for use during execution. • 3. Operators new and delete are used for dynamic memory managements. Concordia TAV 2002 Comp5421_42
Classes Using Dynamic Memory • Class with dynamically allocated data members are a powerful tool in OOP • They allow a program to store variable size data collection and use member function to add, remove, or update items in the collection • To allocate the dynamic memory, the programmer must develop constructor(s) to create objects. • When dynamic memory is involved, the default destructor, default assignment operator, and default copy constructor can lead to disastrous results, such as, memory leaking, and fatal program error. • To avoid these problem, the programmer must develop a destructor, an assignment operator, and a copy constructor. Concordia TAV 2002 Comp5421_42
Class DynamicDemo Declaration • Class declaration: class DynamicDemo { private: char id; // uniquely identifies object for demonstration purpose int value; // value associated with an object int arraySize; // dynamic array arr and number of elements int *arr; // static object used to uniquely identify every object created by the constructor static char uniqueObjId; public: DynamicDemo(int val = 0, int size = 0); // constructor. ~DynamicDemo(); // destructor // assignment operator DynamicDemo& DynamicDemo::operator=(const DynamicDemo& rhs); DynamicDemo(const DynamicDemo& obj); // copy constructor }; char DynamicDemo::uniqueObjId = 'A'; Concordia TAV 2002 Comp5421_42
Static data member • Data member is applied to all instances of the class. • Using static data member, it is like an ordinary global variable only one copy of the variable exists no matter how many instances of the class exist. The main difference is that it is a data member of the class. • It is automatically initialized to 0, so the explicit initialization in the definition is unnecessary unless you want it to have a non-zero initial value. Concordia TAV 2002 Comp5421_42
Static data member class Widget //staticDM.cpp { public: Widget() { ++count; } ~Widget() { --count; } int numWidgets() { return count; }7 private: static int count; }; int Widget::count = 0; int main() { Widget w, x; cout << "Now there are " << w.numWidgets() << " widgets.\n"; { Widget w, x, y, z; cout << "Now there are " << w.numWidgets() << " widgets.\n"; } cout << "Now there are " << w.numWidgets() << " widgets.\n"; Widget y; cout << "Now there are " << w. numWidgets()<< " widgets.\n"; } Concordia TAV 2002 Comp5421_42
DynamicDemo Data Members Static data member uniqueObjId Concordia TAV 2002 Comp5421_42
Constructor • Constructor must allocate the dynamic memory used for the object. Example: DynamicDemo::DynamicDemo(int val, int size) : value(val), arraySize(size) { // record id for object and increment uniqueObjId for // the next object id = uniqueObjId; uniqueObjId++; // dynamically allocate memory for the array arr = new int[arraySize]; // Messsage indicating which object is being created. cout << "Constructor for object " << id << "/" << value << endl; } Concordia TAV 2002 Comp5421_42
main Function int main() { cout << "1. Declare fixed objects in main()" << endl; DynamicDemo mainObj1(1,1), mainObj2(2,2); cout << "2. Declare pointer and allocate a dynamic object“ << endl; DynamicDemo *dynCLPtr = new DynamicDemo(3,3); cout << "3. Deallocate object with 'delete'" << endl; delete dynCLPtr; cout << "4. Ready to exit program." << endl; return 0; } /*1. Declare fixed objects in main() Constructor for object A/1 Constructor for object B/2 2. Declare pointer and allocate a dynamic object Constructor for object C/3 3. Deallocate object with 'delete' Destructor for object C/3 4. Ready to exit program. Destructor for object B/2 Destructor for object A/1 */ Concordia TAV 2002 Comp5421_42
Default Destructor • Memory leak : When a object comes to the end of its life, The destructor function is called automatically to manage its death, if it is not defined explicitly, the default destructor is created automatically. It will destroy all of its data members, and loses all access to their values. • In case of DynamicDemo object, the process destroys the pointer arr that identifies the associated dynamic array. Destroying pointer does not deallocate the corresponding memory for array on the heap, system still think memory is reserved. However, there is no longer a reference to the address through arr. This situation is referred to as a memory leak. • DynamicDemo(int val, int size) : value(val), arraySize(size) • { id = uniqueObjId; • uniqueObjId++; • arr = new int[arraySize]; • } Concordia TAV 2002 Comp5421_42
Default Destructor • Memory leak (1): When delete an object, it destroys all of its fixed data members and dynamic data members, and loses all access to their values. In case of DynamicDemo object, the process destroys the pointer arr that identifies the associated dynamic array. Destroying pointer does not deallocate the corresponding memory for array on the heap, system still think memory is reserved. However, there is no longer a reference to the address through arr. This situation is referred to as a memoty leak. Example: int main() { DynamicDemo *dynCLPtr = new DynamicDemo(3,3);… delete dynCLPtr; return 0; } Concordia TAV 2002 Comp5421_42
Design a Destructor Member Function • Destructor is used to handle this problem. DynamicDemo::~DynamicDemo(void) { delete [] arr; } • Syntax: Form: ~ClassName() Action: Destrucor is automatically called when any object of type className is destroyed. It has no arguments or return value. Its primary role is to call the delete operator and deallocate any dynamic memory that was allocated by the object Concordia TAV 2002 Comp5421_42
Default Assignment Operator • Two problems from default assignment operator dynamic objects, since default assignment only makes a bit-wise copy of data members: 1. Memory leak : DynamicDemo objA(5,3), obj(15,3); objA = objB; //using default assignment operator Concordia TAV 2002 Comp5421_42
Default Assignment Operator (2) 2. Destroying an object sharing a common dynamic array causes a fatal run-time error in any access to another object’s dynamic array: DynamicDemo objA(5,3); { DynamicDemo objB(15,3); objA = objB; //using default assignment }// objB is destroyed, and the destructor de-allocates the dynamic array (p607) //The operation would simultaneously de-allocate dynamic array for objA. Any //access to the dynamic array objA will result in a fatal run-time error Concordia TAV 2002 Comp5421_42
Designing Assignment Operator • Design assignment operator to solve the two problems: DynamicDemo& DynamicDemo::operator= (const DynamicDemo& rhs){ int i; // check arraySize to see if current array can be used if (arraySize != rhs.arraySize) { // de-allocate existing array and allocate new memory delete [] arr; arr = new int [rhs.arraySize]; } // copy fixed data members value and arraySize value = rhs.value; arraySize = rhs.arraySize; // copy items from the rhs.arr to current array for (i = 0; i < arraySize; i++) arr[i] = rhs.arr[i]; // return a reference to the current object cout << "Assignment complete: lhs is object " << id << "/" << value << endl; return *this; } Concordia TAV 2002 Comp5421_42
Designing Assignment Operator (2) • Overloading assignment operator is a class member function with right-hand side operand as single argument; • Function name is “operator=“; • Argument is passed as a constant reference, since its value is not changed; • It must return the value it assigns to itself, since C++ allows for a multiple assignment, objX = objA = objB, i.e. objX=(objA=objB). • To avoid creating a copy, it returns a reference to itself. That’s a preferred prototype. Type& operator=(const Type&); please see the p256-p257 programming with C++, and p609 Ford Comp 248 textbook. Concordia TAV 2002 Comp5421_42
Default Copy Constructor • Also, problems from default copy constructor for dynamic objects, since default copy constructor only makes a bit-wise copy of the data members: Ex. DynamicDemo objB(15,3); { DynamicDemo objA = objB; //using default copy constructor … }//objA is destroyed, and the destructor de-allocates the dynamic array (p612) //The operation would simultaneously de-allocate dynamic array for objB. //Any access to the dynamic array arr in objA will result in a fatal run-time error • Designing a copy constructor to solve the problems Concordia TAV 2002 Comp5421_42
Copy Constructor • Syntax: copy constructor • Form: ClassName(const ClassName& ) • Action: When it is called, it copies the complete state of an existing object into a new object of same class. If class definition does not explicitly include it, then system automatically create one by default • Example: class Ratio { public: Ratio(int n=0, int d=1) ; Ratio(const Ratio& r); //copy constructor declaration private: int num, den; }; Ratio(const Ratio& r) //copy constructor implementation { num = r.num; Den = r.den; } Concordia TAV 2002 Comp5421_42
Call Copy Constructor • Copy constructor is called automatically whenever: 1. an object is copied by means of a declaration initialization; 2. an object is passed by value to a function; 3. an object is returned by value from a function class Ratio { public: Ratio(); Ratio(const Ratio& r); private: int num, den; }; Ratio f(Ratio r) //call copy constructor(2), copy ? To r { Ratio s= r; //call copy constructor(1), copy r To s return s; //call copy constructor(3), copy s To ? } Main() { Ratio x(22,7); Ratio y(x); //call copy constructor(2), copy x To y f(y); } Example: copyCon2.cpp Concordia TAV 2002 Comp5421_42
Design Copy Constructor • // copy constructor. make the current object a copy of obj (p613) DynamicDemo::DynamicDemo (const DynamicDemo& obj) { int i; // set new id for object and increment uniqueObjId for the next object id = uniqueObjId; uniqueObjId++; cout << "Call copy constructor for object " << id << ". Make copy of " << obj.id << "/" << obj.value << endl; // copy fixed data members value and arraySize value = obj.value; arraySize = obj.arraySize; // allocate new dynamic memory for the arr array arr = new int [arraySize]; // copy items from the obj.arr to the newly allocated array for (i = 0; i < arraySize; i++) arr[i] = obj.arr[i]; cout << "Copy complete: created new object " << id << "/" << value << endl; } Concordia TAV 2002 Comp5421_42