std::string::c_str()
returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of t
I'd say that if c_str() returns a const char *
then its not ok, even if it can be argued to be a gray area by a language lawyer.
The way I see it is simple. The signature of the method states that the pointer it returns should not be used to modify anything.
In addition, as other commenters have pointed out, there are other ways to do the same thing that do not violate any contracts. So it's definitely not ok to do so.
That said, Borgleader has found that the language still says it isn't.
I have verified that this is in the published C++11 standard
Thank you
what's wrong with &myStr.front()?
string myStr = "hello";
char* p1 = const_cast<char*>(myStr.c_str());
char* p2 = &myStr.front();
p1[0] = 'Y';
p2[1] = 'Z';
It seems that pointers p1 and p2 are exactly the same. Since "The program shall not alter any of the values stored in the character array", it would seem that the last two lines above are both illegal, and possibly dangerous.
At this point, the way I would answer my own question is that it is safest to copy the original std::string into a vector and then pass a pointer to the new array to any function that might possibly change the characters.
I was hoping that that this step might no longer be necessary in C++11, for the reasons I gave in my original post.
3 Requires: The program shall not alter any of the values stored in the character array.
That requirement is still present as of draft n3337 (The working draft most similar to the published C++11 standard is N3337)
In C++11, yes the restriction for c_str()
is still in effect. (Note that the return type is const
, so no particular restriction is actually required for this function. The const_cast
in your program is a big red flag.)
But as for operator[]
, it appears to be effect only due to an editorial error. Due to a punctuation change slated for C++14, you may modify it. So the interpretation is sort of up to you. Of course doing this is so common that no library implementation would dare break it.
C++11 phrasing:
Returns: *(begin() + pos) if pos < size(), otherwise a reference to an object of type T with value charT(); the referenced value shall not be modified.
C++14 phrasing:
Returns: *(begin() + pos) if pos < size(). Otherwise, returns a reference to an object of type charT with value charT(), where modifying the object leads to undefined behavior.
You can pass c_str()
as a read-only reference to a function expecting a C string, exactly as its signature suggests. A function expecting a read-write reference generally expects a given buffer size, and to be able to resize the string by writing a NUL
within that buffer, which std::string
implementations don't in fact support. If you want to do that, you need to resize
the string to include your own NUL
terminator, then pass & s[0]
which is a read-write reference, then resize
it again to remove your NUL
terminator and hand the responsibility of termination back to the library.