//********************************************
// 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;
        
}

// Source Code Here

 


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