tags:

views:

67

answers:

3

String data

What I am particularly confused about is this statement

"Its contents are guaranteed to remain unchanged only until the next call to a non-constant member function of the string object."

Can someone clarify what does this mean? When to use this and when to avoid using this?

+1  A: 

Sometimes, you need to have access to the string formatted as an array of characters - usually because you need to pass the string to some function which expects the string like this (for example strcmp). You can do this by using the data or c_str members, but you have to respect the rules for calling the function which are spelled out plainly in the link you provided:

The returned array points to an internal location which should not be modified directly in the program. Its contents are guaranteed to remain unchanged only until the next call to a non-constant member function of the string object.

You cannot modify the array of characters - the string object assumes that you do not, and if you do this will lead to undefined behaviour.

1800 INFORMATION
+5  A: 

They mean that you could store the pointer and use it later. If some non-const method is called between two accesses the contents of the buffer your stored pointer is set to may change and your will face unexpected behaviour.

sharptooth
+4  A: 
const char* data() const;

This is saying that the const char * returned by calling str.data() will not change unless someone modifies the string that it came from. Once someone calls a non-constant member function, the returned pointer could be invalid, or could point to different data from what it pointed to immediately after the str.data() function returned.

It means you can pass the returned data to C functions, for example. It means you should not do something like:

const char *old = str.data();
size_t      len = str.length();
...call a function that modifies str...
// cout << old << endl;
// Since old is not guaranteed to be null terminated (thanks MSalter),
// do something else with the old data instead of writing to cout.
// Inventiveness not at a high this morning; this isn't a particularly
// good example of what to do - a sort of string copy.
char buffer[256];
memcpy(buffer, old, MIN(sizeof(buffer)-1, len));
buffer[len] = '\0';

By the time the I/O memory copying is done, old may not be valid any more, and len may also be incorrect.

Jonathan Leffler
Addition:Usually operations on a string cause changes of c-string that is wrapped inside string. As operations like append require reallocation of c-string, it's previous memory location is freed and not used anymore.
Basilevs
"Usually" being the important word, because there are a number of implementations of std::string that don't wrap a C string (the singlemost common exception is not having a \0 in the wrapped char[])
MSalters
Oh, the example is wrong BTW: cout requires a null-terminated string, and data() in general isn't.
MSalters
@MSalters: so you are saying - if the member function had been `c_str` instead of `data`, then the result would be guaranteed null terminated, but given that it is `data`, the result is not guaranteed to be null terminated? ...from the URL in the Q: "_Notice that no terminating null character is appended (see member c_str for such a functionality)_"; OK. My bad. I'm not sure what you can do safely with the result from `data`; you need to know the length, somehow; presumably string::length() gives the right answer. Thanks for the heads up - I missed that detail.
Jonathan Leffler