//******************************************** // Experiments with copy constructor // Shows different situations where the copy constructor is used // 1) initialization using argument(non-default constructor) // 2) initialization using "=" (C-style initialize) // 3) call by value // 4) return by value // also shows that it is NOT used for assignment // In fact demonstrates shallow copy for assignment // Programmer: Chris Wild //******************************************** #include <iostream.h> class classA { friend ostream & operator <<(ostream & os, const classA & theObject); public: classA(); classA(const classA& obj); void update(); void printAddress() const; private: int * p; }; classA::classA() { p = new int[10]; // allocate space for array for(int i=0; i<10;i++) p[i] = i; // note use of array notation with pointer } classA::classA(const classA & obj) { cout << "copy constructor called\n"; p = new int[10]; for(int i = 0; i<10; i++) p[i] = obj.p[i]; // note naming for two objects } void classA::printAddress() const { unsigned addr = (int) &p[0]; cout << "AddressCopy: " << addr << endl; } void classA::update() { for(int i = 0; i< 10; i++) p[i] += 10; } ostream & operator<<(ostream & os, const classA & theObject) { for(int i=0;i<10;i++) cout << " " << theObject.p[i]; cout << endl; return os; } classA someFunction(classA x) // demonstrate call by value, return by value { cout << "entered someFunction\n"; x.update(); return x; } void main() { classA a1; cout << "a1 initially:" << a1; a1.printAddress(); a1.update(); cout << "a1 after update:" << a1; a1.printAddress(); classA a2(a1); // uses copy constructor cout << "a2 initially:" << a2; a2.printAddress(); a2.update(); cout << "a2 after update:" << a2; a2.printAddress(); classA a3 = a2; // uses copy constructor cout << "a3 initially:" << a3; a3.printAddress(); classA a4; cout << "a4 initially:" << a4; a4.printAddress(); a4 = a1; // does not use copy constructor (shallow copy) cout << "a4 after assignment:" << a4; a4.printAddress(); a1.update(); cout << "a1 after update:" << a1; a1.printAddress(); cout << "a4 after update:" << a4; a4.printAddress(); // demonstrates call by value and return by value cout << someFunction(a2) << endl; }
Sample Output
a1 initially: 0 1 2 3 4 5 6 7 8 9
AddressCopy: 207792
a1 after update: 10 11 12 13 14 15 16 17 18 19
AddressCopy: 207792
copy constructor called
a2 initially: 10 11 12 13 14 15 16 17 18 19
AddressCopy: 216048
a2 after update: 20 21 22 23 24 25 26 27 28 29
AddressCopy: 216048
copy constructor called
a3 initially: 20 21 22 23 24 25 26 27 28 29
AddressCopy: 216096
a4 initially: 0 1 2 3 4 5 6 7 8 9
AddressCopy: 216144
a4 after assignment: 10 11 12 13 14 15 16 17 18 19
AddressCopy: 207792
a1 after update: 20 21 22 23 24 25 26 27 28 29
AddressCopy: 207792
a4 after update: 20 21 22 23 24 25 26 27 28 29
AddressCopy: 207792
copy constructor called
entered someFunction
copy constructor called
30 31 32 33 34 35 36 37 38 39