tags:

views:

2315

answers:

2

Hi,

I have read several places that the difference between c_str() and data() (in STL and other implementations) is that c_str is always null terminated while data is not. As far as I have seen in the actual implementation, they either do the same or data() calls c_str().

What am I missing here? Which one is more correct to use in which scenarios?

Thanks.

+17  A: 

The documentation is correct. Use c_str() if you want a null terminated string.

If the implementers happend to implement data() in terms of c_str() you don't have to worry, still use data() if you don't need the string to be null terminated, in some implementation it may turn out to perform better than c_str().

strings don't necessarily have to be composed of character data, they could be composed with elements of any type. In those cases data() is more meaningful. c_str() in my opinion is only really useful when the elements of your string are character based.

Scott Langham
+5  A: 

Even know you have seen that they do the same, or that .data() calls .c_str(), it is not correct to assume that this will be the case for other compilers. It is also possible that your compiler will change with a future release.

2 reasons to use std::string:

std::string can be used for both text and arbitrary binary data.

//Example 1
//Plain text:
std::string s1;
s1 = "abc";

//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);

You should use the .c_str() method when you are using your string as example 1.

You should use the .data() method when you are using your string as example 2. Not because it is dangereous to use .c_str() in these cases, but because it is more explicit that you are working with binary data for others reviewing your code.

Possible pitfall with using .data()

The following code is wrong and could cause a segfault in your program:

std::string s;
s = "abc";   
char sz[512]; 
strcpy(sz, s.data());//This could crash depending on the implementation of .data()

Why is it common for implementers to make .data() and .c_str() do the same thing?

Because it is more efficient to do so. The only way to make .data() return something that is not null terminated, would be to have .c_str() or .data() copy their internal buffer, or to just use 2 buffers. Having a single null terminated buffer always means that you can always use just one internal buffer when implementing std::string.

Brian R. Bondy
Actually, the point of .data() is that it should not copy the internal buffer. This means an implementation does not have to waste a char on \0 until it's needed. You'd never want two buffers: if you DO call .c_str(), append a \0 to the buffer. .data() can still return that buffer.
MSalters
Agreed fully it would be ridiculous to use 2 buffers. How do you know that's why .data was intended though?
Brian R. Bondy