anthes@geocub.greco-prog.fr (Franklin Anthes) (03/20/90)
I'm just starting out with C++. I want to build a very basic String class. BTW I wonder why such basic classes as String, etc. standard in C++? It is a good idea of course to do something like this once or twice during the learning process, but reinventing each wheel can become tedious after a while. Anyway, here's a small piece of my code : typedef unsigned long StringLenType; class String { char *buf; StringLenType len; public: String(); String(const char *); String(const String &); ~String(); String& operator=(const String&); friend String& operator+(String&,String&); } String& String::operator=(const String& s) { len = s.len; delete buf; buf = new char[len+1]; strcpy(buf,s.buf); return *this; } String& operator+(String& s1,String& s2) { String*& ret = new String( s1.len + s2.len ); memcpy(ret->buf,s1.buf,s1.len); memcpy(ret->buf+s1.len,s2.buf,s2.len+1); return *ret; } I want to implement operations like : String s1; String s2("foo"); String s3("bar"); s1 = s2 + s3; // s1 == "foobar" Now the code above "works", but the space allocated by operator+ is not deleted. Is there an elegant way to do this sort of thing in C++? A possible solution (kludge) would be to add a tag into the String class, to indicate whether the string is a temporary which should be deleted after the result is calculated. Hmm garbage collection can come in handy sometimes. A big merci, for those willing to help me me out. -- Frank Anthes-Harper : Bien le bonjour de la France anthes@geocub.greco-prog.fr
ark@alice.UUCP (Andrew Koenig) (03/23/90)
In article <1760@geocub.greco-prog.fr>, anthes@geocub.greco-prog.fr (Franklin Anthes) writes: > typedef unsigned long StringLenType; > class String { > char *buf; > StringLenType len; > public: > String(); > String(const char *); > String(const String &); > ~String(); > String& operator=(const String&); > friend String& operator+(String&,String&); > } operator+ should probably take const String& arguments and return a String result, not a String&. In order to return a String&, there has to be some pre-existing String to which to bind the reference. Since the purpose of operator+ is to create a new String, it is hardly likely that an appropriate String exists. So, without reading further, I would change the declaration to friend String operator+(const String&, const String&); > String& String::operator=(const String& s) { > len = s.len; > delete buf; > buf = new char[len+1]; > strcpy(buf,s.buf); > return *this; > } Almost right. This fails if you assign a String to itself, though. Try it this way: String& String::operator=(const String& s) { char* newbuf = new char[len+1]; len = s.len; strcpy(newbuf,s.buf); delete buf; buf = newbuf; return *this; } > String& operator+(String& s1,String& s2) { > String*& ret = new String( s1.len + s2.len ); > memcpy(ret->buf,s1.buf,s1.len); > memcpy(ret->buf+s1.len,s2.buf,s2.len+1); > return *ret; > } Oops! You allocated memory for `ret' but never freed it, as I suggested earlier might happen. Also, I don't understand how `new String(s1.len + s2.len)' can work unless you have String(int) defined to allocate that much memory, which doesn't appear in your declaration. Try it this way: String operator+(const String& s1,const String& s2) { String ret; ret.buf = new char[s1.len + s2.len + 1]; memcpy(ret.buf,s1.buf,s1.len); memcpy(ret.buf+s1.len,s2.buf,s2.len+1); return ret; } For this to work, you must have defined String(const String&) correctly. For example: String::String(const String& s) { buf = new char[s.len + 1]; memcpy(buf,s.buf,s.len+1); len = s.len; } > Now the code above "works", but the space allocated by operator+ is not > deleted. Is there an elegant way to do this sort of thing in C++? The strategy outlined above should avoid all memory leaks. -- --Andrew Koenig ark@europa.att.com