c++stdstringconst-castc-str

Is it safe to use std::string::c_str() to modify the underlying std::string?


I came across some code which has several instances of the bellow example:

std::string str = "This  is my string";
char* ptr = const_cast<char*>(str.c_str());

ptr[5] = 'w';
ptr[6] = 'a';

In this simplified example there is an assignment of std::string::c_str(), which returns const char*, to a char* pointer using const_cast.

This seems to work as intended and str is modified accordingly.

But the description of std::string::c_str() in my local library reads as follows:

Return const pointer to null-terminated contents. This is a handle to internal data. Do not modify or dire things may happen.

And in cppreference the description includes:

Returns a pointer to a null-terminated character array with data equivalent to those stored in the string.

...

Writing to the character array accessed through c_str() is undefined behavior.

In the standard [string.accessors] the descritpion is similar and no information about this ...null-terminated character array with data equivalent to those stored in the string... is provided.

Instead of clarifying the issue, this confused me further, what character array? How is it equivalent? Is it a copy? And if so why is modifying it, also modifying the original string? Is this implementation defined?

I would like to avoid the task of altering all the instances of the code where this is used, so my question is:

Is there any way this can be correct, can it be legal to use ptr pointer to modify str string?


Solution

  • The reference for c_str that you cited is quite clear on the matter:

    The program shall not modify any of the values stored in the character array; otherwise, the behavior is undefined.

    The fact that it happens to work doesn't mean anything. Undefined behavior means the program could do the "right" thing if it wants to.


    If you do want to modify the underlying data, you can use the non-const overload of data(), which is available from C++17, which allows you to modify all but the null-terminator:

    The program shall not modify the value stored at p + size() to any value other than charT(); otherwise, the behavior is undefined.