Sign in to follow this  

Static strings: string or char*?

This topic is 4759 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've started using STL strings in my code for security, and love how easy they are to use. But what about static read-only strings? Like, lets say you have a hard-coded array of text strings, that are never modified, just read. Would you go so far as to make them string objects as well, or is char* sufficient in this case? Maybe strings can't even be used in that way, I don't know. I'm assuming char* is safe enough if the string length is known? Or am I missing something?

Share this post


Link to post
Share on other sites
You can use std::strings like that, but it's largely pointless, and may fragment your heap somewhat. Just remember that, if you need it, you can convert a char * to a string object and think happy thoughts.

Share this post


Link to post
Share on other sites
Write down this equation in your compiler, run and think if such memory overhead when using X sized array of strings can be accepted.

std :: cout << sizeof(std::string) * X << endl;

If you're writing program or small game, odds are that you shouldn't care so much about performance ("Premature optimization is the root of all evil" etc.), but if you're writing game, and this game must run fast on a variety of comptuers... that's different situation.

-------

As for me, I'm using std::strings in case when I've got need to do sth more complicated with it; also remember that strings are neat and handy, but they come with a price and if you care about performance you should be carefull, ie. don't EVER pass them as function arguments:

void function(const string & _blablabla);

instead use:

void function(const char * _blablabla);


and if you need to do sth with _blablabla then simply:


void function(const char * _blablabla)
{
string foo(_blablabla);
...
}

Share this post


Link to post
Share on other sites
just out of intrest, why would you use it like that? I'd have thought that passing a const std::string& would be more logical, there is no copy of the string made, where as on the 2nd method you have to make a function call to get the address of the string back and on the 3rd version you have to make that same call THEN construct a new string to use AND destroy said string at the end of the function.

Now, call me daft, but isnt that going to increase the overhead alot more vs just passing a const std::string& in?

Share this post


Link to post
Share on other sites
Quote:
Original post by _the_phantom_
Now, call me daft, but isnt that going to increase the overhead alot more vs just passing a const std::string& in?

Shhh, common sense is never as fun as dogma!

Seriously though, if you're gonna mess with the string (searching/appending/trimming/etc) put it in a string class. If you're just passing it around, do whatever's easiest.

I have browsed the Netscape Gecko sourcecode, and they have several string classes:
* weak pointers to strings (char* wrappers)
* small strings (allocates from a 64KB buffer)
* strong pointers to strings (char* wrappers)
* ropes (for large strings)

Iterators are used to traverse the strings so the differences aren't noticeable unless you are making OS calls.

[Edited by - antareus on December 1, 2004 9:37:05 AM]

Share this post


Link to post
Share on other sites
when you do a line like this:

char myString[] = "some message";

remember that the buffer is a copy and is not constant, but when you do this:

char *myString = "some message";

the buffer is a constant char array and you CANNOT modify it (you will get either compile time warnings or runtime errors) ... so it is much better to be explicit about this and write:

const char *myString = "some message";

Share this post


Link to post
Share on other sites
I use std::string a lot, in fact for any and all text manipulation I do unless I see a major reason not to. - but I use 'const char *' when initializing compile time constant strings. And since you can create const char * from strings and strings from const char *, then it's no problem.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
explain why void someFunc(const string& s) {} would be bad?
the string is passed as a reference and not as a copy plus it's more elegant, makes more sense, less errorprone/more typesafe than passing char*.

Share this post


Link to post
Share on other sites
Quote:
Original post by Anonymous Poster
explain why void someFunc(const string& s) {} would be bad?
the string is passed as a reference and not as a copy plus it's more elegant, makes more sense, less errorprone/more typesafe than passing char*.


And when you pass "const char *" you'll get a string automatically anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by _the_phantom_
no, you'll get a pointer to a const character array, they just happen to be used as strings, thats all [smile]


No, string literal is not an l-value so a temporary std::string object will be created and bound to the reference.

Share this post


Link to post
Share on other sites
wanna run that by me again... why would passing a pointer to a character array get promted to an std::string? They arent even the same time, why on earth would the compiler automagically do that promotion? If I try to write to the constant char array then I'd expect the compiler to scream at me about it, not do silly autopromtion tricks... unless someone has invented the DWIM switch for the compilers and not told me [wink]

Share this post


Link to post
Share on other sites
Because the string class has a constructor that takes a char const*. Now, as every "good" C++ book teaches you, a C++ compiler can make at most one implicit casts to a type, so since there is an available constructor, the compiler can implicitly cast the char const* to a std::string by calling the appropriate constructor.

Share this post


Link to post
Share on other sites
hmmm yes I follow that and have used it in the past [smile]

I think I see the issue here, I might well have misread the intent of MagicScript's post, I'm now thinking that he ment if you define the function as taking a const std::string & and pass it a const char * then you'll get a string, which ofcourse is correct, however I thought at the time that he ment if you passed and wanted a const char * then it would be a string anyways (as in changeable via the C lib. str*() functions), thus when fallenang3l brought std::strings into the mix it all got rather confusing [smile]

Share this post


Link to post
Share on other sites
Hmmm, as for that const string & question... I didn't invent it myself, source: Game Programming Gems #2, author: Andrew Kirmse, LucasArts. (though I did invent that: string foo(_blablabla), sure, in this case, in one possible situation I was wrong, but read to the end of my post)

Kirmse explains that for this kind of code:


void Function(const std::string &str)
{
...
}

Function("Hello");



calling Function would call constructor (with parameter const char *), which often calls malloc(), strlen and memcpy(), and when str is going to be destructed, obviously free() is going to be called and in implementaton which uses reference counted strings, Slow Things will happen... In this situation we've just duplicated the string in memory cause it's already in program memory segment. And dynamic allocation is slow and can be very wastefull when inproperly used, especially in main loop or often called functions.

Ok, you may say that when we pass some const char * that's generated at runtime ie. typed by the user, then it won't be such wastefull. Well, I honestly say that depends on the situation. If you use that string just for some basic operation ie. searching texture in map of textures, then std::strings obviosly create unnecessary overhead. But if you do some sort of parsing... sure, why not use std::strings, in this case it would be the same as using that second method.

And one last thing: when dealing with COM interface writing or when you need to create DLL that can be used in other programming languages, then passing std::strings as arguments is forbidden, you must use const char * (though you can later initialize some local string with that argument, now you know why I've written that second case...)

Share this post


Link to post
Share on other sites
the main thing is, if you want efficiency, you should pass around 1 or the other of the 2 in almost all cases, so you don't have to promote and wrap, or lock down for conversion ...

basically, either use const char * in as many places as possible (basically anywhere that is not supposed to modify the string) OR use const string & in as many places as possible ... but don't use both ...

of course for things which need to do modification, they should take string &, char *, or char ** depending on their expected needs ... it is silly to take a char * as input to a function that's going to do work using a string, and then copy back the resulting char * ... and it's silly to take string& when your algorithm needs to copy into a character buffer, modify, and then assign back ...

Share this post


Link to post
Share on other sites
MS VC7 => sizeof(std::string)==28
G++ 3.4.2 => sizeof(std::string)==4 !

How does this work? G++ allocates 12 additional bytes directly in front of the char[] that stores the actual string to store all management data.
So std::string doesn't have to have a big overhead over raw char*.

Share this post


Link to post
Share on other sites

This topic is 4759 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this