Click here to Skip to main content
15,890,845 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
hi, i constructed my own string class where i use char* str
the below is the piece of code

From below code snippet, In param constructor and copy constructor
cstr = str; //this part of statement works fine.

but even then why i need to allocate memory using new and then strcpy required?
cstr = new char[strlen(str) +1];
strcpy(cstr, str);

both works fine. but why to choose dynamic allocation method?

What I have tried:

C++
class CString
{
private:
	char* cstr;
public:
	CString();
	CString(char* str);
	CString(CString& str);
	~CString();

	operator char*();
	//operator const char*();
	CString operator+(const CString& q)const;
	CString operator=(const CString& q);
};
CString::CString()
{
	cout << "constructor" << endl;
	cstr = 0;
}
CString::CString(char *str)
{
	cout << " param constructor" << endl;
	//cstr = str;// this works fine even then we allocating with new why???
	cstr = new char[strlen(str) +1];
	strcpy(cstr, str);
}
CString::CString(CString& q)
{
	cout << " copy constructor" << endl;
	if (this == &q)
		return;
	cstr = q.cstr;
	//cstr = new char[strlen(q.cstr) + 1];
	//strcpy(cstr, q.cstr);
}
CString::~CString()
{
	//if (cstr)
	//	delete[] cstr;
}
CString::operator char*()
{
	cout << " operatorcahr*" << endl;
	return cstr;
}
//CString::operator const char* ()
//{
//	cout << " const operatorcahr*" << endl;
//	return cstr;
//}
CString CString::operator +(const CString &q) const
{
	cout << "operator +*" << endl;
	CString s;
	s.cstr = new char[strlen(cstr) + strlen(q.cstr) + 1];
	strcpy(s.cstr, cstr);
	strcat(s.cstr, q.cstr);
	return s;
}
CString CString::operator =(const CString &q)
{
	cout << "operator =" << endl;
	if (this != &q)
	{
		//if (cstr)
			//delete[] cstr;
		cstr = new char[strlen(q.cstr) + 1];
		strcpy(cstr, q.cstr);
	}
	return *this;
}

int _tmain(int argc, _TCHAR* argv[])
{
	CString a = CString("Hello") + CString(" World");
	cout << a << endl;
	getchar();
	return 0;
}
Posted
Updated 29-Nov-16 1:05am
v2
Comments
Philippe Mori 29-Nov-16 10:17am    
Although writing a string class is a good exercise, one should usually use standard string class in production code as the standard class was coded by experts who have a better understanding of pitfalls like those.
Philippe Mori 29-Nov-16 10:24am    
One example where your code would probably fails is CString a = CString() + CString(" World");. That is if you replace the first constructor call so that the default constructor is used.

Also operator= should return a reference.

If you use cstr = str; then your class just contains a pointer to the external initialisation string, which could be modified outside of your class. If you take a copy of it, you have complete control over your class's internal string.
 
Share this answer
 
Comments
Member 11732139 29-Nov-16 7:33am    
Hi, thank you the reply.
can you give more detail with example that what do mean by "which could be modified outside of your class" from your ques

did you mean copyconstructor should have const as param?
CString::CString(const CString& q)
hairy_hats 29-Nov-16 7:47am    
Suppose you had:

char [] hello = "Hello, world!";

CString string(hello); // string contains "Hello, World!"

strcpy(hello, "Goodbye!");

If you use cstr=str; then string now contains "Goodbye!" even though you changed hello. If you allocate your own memory and copy the initialisation text, then your class's internal text doesn't change.
Philippe Mori 29-Nov-16 10:10am    
Even worst would be data on the stack or that are otherwise deleted while the string still reference that copy...
With a string you have some memory where it is actually stored and you have a pointer to this memory which references the string. If you want to create a copy of the string you must copy the memory which requires allocating new memory for it.

There are also some errors and possible optimisations in your code.

For example you should delete the old memory when allocating a new block and when the object is destroyed:
CString CString::operator =(const CString &q)
{
    cout << "operator =" << endl;
    if (this != &q)
    {
        // No need to check if cstr is NULL.
        // delete does nothing in this case.
        delete[] cstr;
        // But check here if q.cstr is NULL!
        if (q.cstr)
        {
            cstr = new char[strlen(q.cstr) + 1];
            strcpy(cstr, q.cstr);
        }
        // String is empty now
        else
            cstr = 0;
    }
    return *this;
}


CString::~CString()
{
    delete[] cstr;
}

Once you have implemented the assignment operator, it can be used by other functions:
C++
CString::CString(const CString& q)
{
    cout << " copy constructor" << endl;
    *this = q;
}

Knowing this it might be better to have a CString::CString(const char *s) assignment operator instead because that can be used for multiple copy constructors.
 
Share this answer
 
v2
Comments
Member 11732139 29-Nov-16 7:36am    
did you mean i did shallow copy ... for deep copy you need to allocate memory ..
is that my understanding correct!!
Jochen Arndt 29-Nov-16 8:04am    
Yes.
When a class contains allocated memory you need deep copy (allocating and copy the content).
Shallow copy is copying the content of the members which would be coyping the char* pointer in your case.
[no name] 29-Nov-16 8:07am    
Yes, absolutely correct. Since a shallow copy would break the encapsulation of your class, you must do a deep copy.
Philippe Mori 29-Nov-16 10:14am    
Generally, it is better to implement operator= using the copy constructor and swap idiom as it make it easier to write exception safe code.

Also, in your case, the copy constructor might fails while calling the assignment operator since cstr has not yet been initialized.
Member 11732139 30-Nov-16 0:50am    
Thank you ... found some improvement in my understanding.
am still not clear why CString::CString(const char *s) is required...!!!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900