🎉 Celebrating 25 Years of GameDev.net! 🎉

Not many can claim 25 years on the Internet! Join us in celebrating this milestone. Learn more about our history, and thank you for being a part of our community!

Using strings in C++

Started by
11 comments, last by Foopy 24 years, 7 months ago
Okay, surely in your constructor/destructor/overridden = operator you can deallocate the memory as you go?
Wherever the myObject object comes from, it must have an area of view (even if it's the lifetime of the program) at which point it's destroyed and you can run your free functions on the necessary areas of allocated memory.
If the toString function returns a pointer to a char* from the myObject private variables, then the memory is later deallocated by the myObject destructor. If it creates a local variable and passes that back then the memory is already deallocated the second the toString function ends. You then have a string inside the String object you were writing to but that's deallocated by it's own destructor.
Where's the problem, unless I've missed the point.
Advertisement
Ok, I'm sorry my last post was confusing. I didn't quite understand what you said, but hopefully this will clarify things. Take this pseudocode example:

class String {private:  /* Pointer to the null-terminated     string. */  char *stringData;public:  /* Makes a copy of source, points     stringData to it. */  String(const char *source);  /* Frees stringData, if it's non-null. */  ~String();  /* Prints stringData to the screen. */  printMe();};String Test() {  String temp("hello.");  // Do some stuff with temp here.  return temp;}void main() {  Test().printMe();}

Now, the problem with this is that temp's destructor will be called when the Test() function exits, thereby destroying the stringData, so when Test().printMe() is called in the main() function, the stringData of the String object has been freed already. I suppose I could make my own copy constructor for the String class that does a deep copy of the object instead of a shallow copy, but this means the entire stringData would have to be copied when Test() returns temp, which would slow things down. I suppose I could just do that, but is there any easier way to do this (that doesn't involve copying the entire string with the copy constructor) that I'm missing?

So your trying to pass back a local variable which is a class, which is destroyed on exit from the function Test.
Okay, surely if you want to print the string you merely put the variable in the main function or have the printMe call in the Test function. What you appear to be doing is the equivilant of creating a local struct or array and trying to pass it back through the return value.
This is a dangerous practice, which normally works because the area of memory is freed but not overwritten in the following steps between you returning and trying to use it.
So, unless your destructor physically changes the memory address you're returning, then it should still contain the correct info to be printed.
Not guaranteed though and a better way would be to have Test using a String* temp and using
temp = new String("hello.")
returning that and deleting it later, perhaps with a printMeAndDelete function.
I don't see the need to do what you're trying to do, but then I can't see an answer either.
If I knew why you were trying to do it that might make it easier to understand.
I have often had the same problem. What I ended up doing was making an array of global values that have their pointers returned with the function, so that when it ends, the value is still there. All the function needs to do is figure out which one is free for use and use it.

Another more dangerous (most likely suicidal) practice would be to gave a single global pointer that points to a new string each time the function returns. As long as you hang on to the pointer before it is overwritten with the next new call, you will be fine. If you don't hang onto it and don't delete it, you will end up with a pretty bad memory leak.

I don't know if it has any bearing on the more recent posts, but in the first post of this thread, it seemed to me like you wanted a way to parse and combine strings. To parse them, you can use a header I wrote, and to combine strings, use sprintf(). It can be found in either stdio.h or stdlib.h, I don't remember which. If you want the string parsing / wordcounting / chatterbot making header file, go to my website at: www.trak.to/rdp


actually, this is the type of problem that providing your own copy constructor will solve.

Since you haven't provided a copy constructor, the compiler provides one for you using a bitwise copy.

This is not what you want as you will be referencing the same data.

e.g.

//: with bitwise copy
String B = A;

B will reference same data as A.

With a copy ctor, B will have its own copy of the data.

So, in your function:

String Test() {
String temp("hello");

return temp;

}

temp is going to be destroyed when it goes out of scope, but not before a temporary copy is made to be returned.

HTH,

-mordell

__________________________________________

Yeah, sure... we are laughing WITH you ...
All I can say is: exactly on the money. A copy constructor that really makes a second copy of the character data will work fine. If you need a light-weight string class, I can send you one. Just email me.

- Splat

Wouldn't the standard template library (STL)

#include

allow you to work with strings in C++ and handle memory allocation and deallocation ?


Yes, the STL string class would be my choice for string handling.

However, building your own string class is probably one of the most used examples of how to implement operator overloading (and a good one).

I still have my old string class, but I don't use it. I use the widely accepted STL string.


-mordell

__________________________________________

Yeah, sure... we are laughing WITH you ...
There is no need for a copy constructor. Replace the line

String temp("hello");

with

String *temp = new String("hello");

using new means that it is created on the heap. As such will not get deleted on exit of the function. This in itself is bad practice as you will have to expicitly call delete at some point in your program. You can get around this by creating a smart pointer class (i.e. a wrapper for standard pointers which will monitor all pointers and will dealocate memory off the heap when the program terminates). SP`s are simpleish to code, its just a case of overloading * and -> then making sure you monitor all new, copy and equateing operators and dealocate them.

giz a email if you want to know more!

hamfdeath@yahoo.com

The idea of "new"ing the necessary data and returning it was brought up in a previous post.

While it would work, it would be easy to forget to delete the data returned from the function.

Also, I am not sure how a smart pointer with a scope local to that function would be able to exist outside that function?

Granted, I am not an authority on smart pointers, but my understanding is while they may free the developer from the duties of cleanup, the don't ignore the laws of variable scope.

So, when the program flow exits the function, the smart pointers dtor would be called, freeing the pointer, right?

Regardless, while the use of the copy ctor is not necessary to resolve the issue, I think it would be the cleaner implementation.

-mordell


__________________________________________

Yeah, sure... we are laughing WITH you ...

This topic is closed to new replies.

Advertisement