The copy constructor: Object initialization

Discussion in 'C++' started by rahulnaskar, Nov 30, 2006.

  1. rahulnaskar

    rahulnaskar New Member

    Joined:
    Aug 26, 2004
    Messages:
    25
    Likes Received:
    2
    Trophy Points:
    0

    Introduction



    Memory allocation for objects is a tough issue, sometimes. Dynamically allocated memory has to be treated specially when one object is used to initialize another. In default constructor a bit wise copy is done when one object is assigned to another, leaving no room for separate memory allocation and hence copy constructor.

    Consider the class:
    Code:
    class clsString
    {
    private:
    int lenName;	//Length of the string, not required for dynamic memory allocation
    char *strName;	//The string, required to have dynamic memory allocation
    public:
    	//The constructor where memory is allocated
    	clsString(char *s="")
    	{
    		lenName = strlen(s)+1; 
    		strName = new char[lenName]; //Dynamic allocation
    		strcpy(strName,s);
    	}
    	//Destructor where memory is freed
    	~clsString() {cout << "In destructor Name is " << strName << " and length is " << lenName << endl; delete[] strName;}
    	//Returns the value where data is stored in allocated memory
    	char * getName() {return strName;}
    	//Returns the value where data is stored not by allocating memory
    	int getLen() {return lenName;}
    };

    Using the code ...



    The constructor is default and strip of memory is allocated, which is also destructed during deallocation of the memory. When one object of this class is used to initialize another object of the type, we have a serious problem. The problem is that both the objects will be pointing to the same memory location belonging to the data member strName. When one object is destructed the other one will be pointing to a portion of memory, which has already been freed and will generate a run-time error.

    Consider using the class in the following way:
    Code:
    int main()
    {
    	//Explicit initialization
    	clsString myName("Bill Gates");
    	//Initialization by existing object
    	clsString myDuplName=myName;
    	//Object 1 data
    	cout << "Initial Object Name: " << myName.getName() << endl;
    	cout << "Initial Object Length: " << myName.getLen() << endl;
    	//Object 2 data
    	cout << "Copied Object Name: " << myDuplName.getName() << endl;
    	cout << "Copied Object Length: " << myDuplName.getLen() << endl;
    	cout << "---------------------------" << endl;
    	cout << "---------------------------" << endl;
    	return 0;
    }
    Note: When run from MS VC 6 IDE, you will notice an error when the destructor is called for the second time. It will try to free a memory location which has already been freed and hence the error.

    Try testing the results by copying the code, pasting it in a new project and running the same.

    The resolution:



    Copy constructors should be used in cases similar to these to avoid the problem mentioned. Consider using the same class with copy constructor attached along with the default constructor.

    Code:
    class clsString
    {
    private:
    	int lenName;	//Length of the string, not required for dynamic memory allocation
    	char *strName;	//The string, required to have dynamic memory allocation
    public:
    	//The constructor where memory is allocated
    	clsString(char *s="")
    	{
    		lenName = strlen(s)+1; 
    		strName = new char[lenName]; 
    		strcpy(strName,s);
    	}
    	//The copy constructor
    	clsString (const clsString& t)
    	{
    		lenName = t.lenName;
    		strName = new char[lenName]; 
    		strcpy(strName,t.strName);
    	}
    	//Destructor where memory is freed
    	~clsString() {cout << "In destructor Name is " << strName << " and length is " << lenName << endl; delete[] strName;}
    	//Returns the value where data is stored in allocated memory
    	char * getName() {return strName;}
    	//Returns the value where data is stored not by allocating memory
    	int getLen() {return lenName;}
    };
    
    When this piece of code is used no error is generated. During initializing the existing object is passed as the parameter to the copy constructor, which is a const. Reallocate your necessary memory and all those stuff you require without disturbing any existing objects by the copy constructor.

    Copy constructors have the same effects when an object is passed on as a function parameter or is returned by a function. I will probably write on both of them in my coming article.

    Try tweaking around the code attached.
     

    Attached Files:

  2. rahul.mca2001

    rahul.mca2001 New Member

    Joined:
    Feb 13, 2008
    Messages:
    103
    Likes Received:
    0
    Trophy Points:
    0

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice