If I need to get a NUL-terminated char
array out of a std::string
in a situation where I need to be sure nothing will be allocated, is it safe to use c_str
to do so? For example, if I'm inside a destructor and I want to copy some data from a string
into a pre-allocated, fixed-size buffer, can I use c_str
and be sure it won't throw anything?
views:
128answers:
4No, the standard gives no such guarantee. The only guarantee in the C++ standard is that the returned value points to a char
array with the same contents as the std::string
, plus a nul-terminator.
So it would be standards-conforming for an implementation to store its internal representation in some way other than a C-string, and allocate a C-string on the fly when you call c_str
, although I'm fairly certain that no widely used STL implementation actually does this.
Now, with respect to C++0x, I have heard (although I am at a loss for finding documentation for this at the moment), that one of the changes is going to be to require that std::string
operate on contiguous storage (a similar requirement already exists for std::vector
). So in that case, you could access the span from &str[0]
through &str[0]+str.length()-1
as if it were a C-string without a nul-terminator.
The standard says that calling c_str()
may invalidate references, pointers, and interators referring to the elements of the string
, which implies that reallaocation is permitted (21.3/5 "Class template basic_string").
You might want to just call string::copy()
to get your copy (you'll need to add the null terminator yourself if you need it).
The Standard is silent on this:
21.3.6 [lib.strings.ops]
const charT * c_str () const ; 1 Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements equal the corresponding elements of the string controlled by *this and whose last element is a null character specified by charT().
2 Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the returned value as a valid pointer value after any subsequent call to a non-const member function of the class basic_string that designates the same object as this.
It could. That said, Iv'e never seen any implementation that does.
If this is a concern for you, you may want to consider using vector<char>
instead of string
, and doing something like:
vector<char> chars;
// ...
char* my_str = &chars[0];
The trick here is knowing when & how to deal with the need for '\0'
-terminated strings.
The standard all but explicitly says that a string can allocate memory when you call c_str
. In particular, it says (§21.3/5):
References, pointers, and iterators referring to the elements of a basic_string sequence may be invalidated by the following uses of that basic_string object:
[ ... ]
— Calling data() and c_str() member functions.
It gives permission for pointers, references and iterators to be invalidated specifically to allow an implementation to re-allocate the memory used to store the string when you call c_str
.