260 likes | 374 Views
Deep Copy vs Shallow Copy. Copy Constructor. The Big Three. Copy Constructor Assignment operator = Destructor. If you need one of them, you need all of them. Overload assignment = as a member function. a = b = c = d = e;. class point { public: .....
E N D
Deep Copy vs Shallow Copy Copy Constructor IT 279
The Big Three • Copy Constructor • Assignment operator = • Destructor If you need one of them, you need all of them IT 279
Overload assignment = as a member function a = b = c = d = e; class point { public: ..... point &operator = (const point & a); ..... private: doublemy_x; doublemy_y; ..... }; return type function name parameter list this is the pointer of the calling object C = (A = B) point & point::operator = (const point & a) { my_x = a.my_x; my_y = a.my_y; return*this; // return as this so we can use a=b=c; } A’smy_xandmy_y (A is the calling object) IT 279
If x is an pointer, use -> instead of . (dot operator) Using = and -> class point { public: ..... point &operator = (const point & a); ..... private: ..... }; point *a, *b; a = new point(5,6); b = new point; .... printp(*a); a->distance(*b); a = b; point a,b(4,5); ..... a = b; .... a = point(2,3); // a = new point(1,2); All = in this block are not the operator = defined in class point. IT 279
class point { public: ..... point &operator = (const point & a); ..... private: ..... }; What can we do?C++’s way point a,b(4,5); ..... a = b; a = point(1,2); point *a, *b; b = new point(1,2); a = new point(5,6); *b = *a; a=b; point *a, *b; a = new point(5,6); b = a; point *a, *b; a = new point(5,6); *b = *a; point *a, *b; a = new point(5,6); *b = point(1,2); point a,b(4,5); ..... a = b; a = new point(1,2); point *a, *b; b = new point(5,6); *b = point(1,2); point *a, *b; a = new point(5,6); b = new point(1,2); *b = *a; IT 279
The destructor : to destroy an object printp .... .... .... p: string printp(point p) { ...... } int main() { point v(4,5); .... cout << printp(v); ..... } ..... ..... my_x my_y Constructed by the constructor Copied by the copy constructor v: ..... ..... When printp(v) in the main function is done, the copy of v must be destroyed. The destructorof Point will be called to do the job my_x my_y IT 279
Define a destructor class point { public: ..... point &operator = (const point & a); // assignment operator point(constpoint& a); // copy constructor ~point(); // destructor ..... private: double my_x; double my_y; ..... }; .... point::~point() // nothing to be done; {} In fact, class point doesn’t need to explicitly program the big three; namely, the default ones can do the job. IT 279
Dynamic arrays, resizable arrays a p i int a[3]={5,60,700}; int *p,i; p = newint[3]; for (i=0; i<3; i++) p[i] = i; p = newint[i]; for (i=0; i<4; i++) p[i] = i*i; 1 4 5 3 1 2 2 4 IT 279
Delete Dynamic arrays a p i int a[3]={5,60,700}; int *p,i; p = newint[3]; for (i=0; i<3; i++) p[i] = i; delete [] p; p = newint[4]; for (i=0; i<4; i++) p[i] = i*i; 1 3 1 4 2 3 IT 279
Shallow Copy class Stack { ..... private: int my_size; int *my_stk; // pointer to a dynomic array ..... }; Shallow copy can be done by default copy constructor Stack a ...... Stack b ...... my_size my_stk my_size my_stk Shallow Copy IT 279
Deep Copy class Stack { ..... private: int my_size; int *my_stk; // pointer to a dynomic array ..... }; Deep copy needs to program the copy constructor ...... Stack b my_size my_stk Stack a ...... my_size my_stk new int[4] Deep Copy IT 279
Dynamic Arrays and The Big Three In general, if a dynamic array is used in the class, then its big three need deep copy. • Copy Constructor • Assignment operator = • Destructor Java doesn’t have the destructor IT 279
Stack Class class Stack // First in last out { public: Stack(); // default constructor Stack(int *a, int n); // construct and push array a into the stack int pop(); // pop out the top element int push(int a); // push a into the stack int size(); // return the size of the stack; // The following three are so-called the Big Three; // They need to handle the dynamic array *my_size; Stack(const Stack & a); // 1. copy constructor; Stack & operator=(const Stack & a); // 2. assignment operator; ~Stack(); // 3. destructor; private: int *stk; int my_size; int head, tail; }; IT 279
The Copy Constructor Stack::Stack(const Stack & a) // 1. copy constructor; { my_size = a.my_size; my_head = a.my_head; my_tail = a.my_tail; stk = newint[my_size]; for (int i =0; i<my_size; i++) stk[i] = a.stk[i]; } ...... Stack b Stack a ...... new int[4] Deep Copy IT 279
Deep Copy for Assignment a = b b ...... my_size my_stk a ...... my_size my_stk Deep Copy IT 279
Problem of Deep Copy for Assignment a = b b ...... my_size my_stk a ...... 3 my_size my_stk Deep Copy wasted IT 279
Problem of Deep Copy for Assignment a = b b ...... my_size my_stk a ...... 5 my_size my_stk Deep Copy This location belongs to someone else 10 IT 279
Stack & Stack::operator=(const Stack & a) // 2. assignment operator; { my_size = a.my_size; my_head = a.my_head; my_tail = a.my_tail; stk = new int[my_size]; for (int i =0; i<my_size; i++) stk[i] = a.stk[i]; return *this; // So, we can use a=b=c; } Operator = a = b We have problem! a ...... b ...... 3 my_size my_stk my_size my_stk Deep Copy wasted IT 279
Solution for Assignment a = b b ...... my_size my_stk a ...... 5 my_size my_stk new int[5] Deep Copy delete IT 279
Another Problem for Assignment Stack & Stack::operator=(const Stack & a) // 2. assignment operator; { my_size = a.my_size; my_head = a.my_head; my_tail = a.my_tail; delete stk[]; stk = new int[my_size]; for (int i =0; i<my_size; i++) stk[i] = a.stk[i]; return *this; // So, we can use a=b=c; } We still have problem! new int[4] a ...... my_size my_stk delete Deep Copy a = a IT 279
Correctly overload = Stack & Stack::operator=(const Stack & a) // 2. assignment operator; { if (my_size != a.my_size) { delete [] stk; stk = new int[a.my_size]; } my_size = a.my_size; my_head = a.my_head; my_tail = a.my_tail; for (int i =0; i<my_size; i++) stk[i] = a.stk[i]; return *this; // So, we can use a=b=c; } IT 279
Desctructor Stack::~Stack() // 3. destructor { delete [] stk; } Just delete all dynamic arrays created in this class. IT 279
// Base class class A { public: A(int a); A(const A & a); //Copy constructor; A & operator = (const A & a); // overload = ~A(); // Destructor; ..... private: int size_A; int *array_A; }; Inheritance and Big-Three // Derived class class B : public A { public: B(int b); B(const B & b); //Copy constructor; B & operator = (const B & b); // ~B(); // Destructor; ..... private: int size_B; int *array_B; }; In private section!! Use A’s constructor IT 279
// Derived class class B : public A { public: B(int b); B(const B & b); //Copy constructor; B & operator = (const B & b); // ~B(); // Destructor; ..... private: int size_B; int *array_B; }; Inheritance and copy Constructor // Derived class B::B(const B & b) :A(b) // call the copy constructor of A; { size_B = b.size_B; array_B = newint[size_B]; for (int i=0; i<size_B; i++) array_B[i] = b. array_B[i]; } IT 279
// Derived class class B : public A { public: B(int b); B(const & B); //Copy constructor; B & operator = (const B & b); // ~B(); // Destructor; ..... private: int size_B; int *array_B; }; X = Y Inheritance and assignment = // Derived class B & B::operator = (const B & b) { A::operator=(b); if (size_B != b.size_B()) { delete [] array_B; array_B = newint[size_B]; }; for (int i =0; i<size_B; i++) array_B[i] = b.array_B[i]; return *this; } This will take care of the variables in the base class IT 279
// Derived class class B : public A { public: B(int b); B(const & B); //Copy constructor; B & operator = (const B & b); // ~B(); // Destructor; ..... private: int size_B; int *array_B; }; Inheritance and destructor Mind your own business // Derived class B::~B() { delete [] array_B; } IT 279