C ++ const cast, unsure if it's safe

This may be a dumb question, but I really need to clarify this:

Will this be a danger to my program?

Is const_cast ?

If I change the values ​​of the input pointers in place, will it work safely with std::string or will it create undefined behavior?

So far, the only problem is that this may affect the string "some_text" whenever I change the input pointer and makes it unusable.

 std::string some_text = "Text with some input"; char * input = const_cast<char*>(some_text.c_str()); 

Thank you for giving me some advice, I would like to avoid shooting on my own leg.

+7
source share
9 answers

As an example of bad behavior: interaction with the implementation of gcc Copy On Write.

 #include <string> #include <iostream> int main() { std::string const original = "Hello, World!"; std::string copy = original; char* c = const_cast<char*>(copy.c_str()); c[0] = 'J'; std::cout << original << "\n"; } 

In action on ideone .

Jello, Peace!

Problem? As the name implies, the gcc implementation of std::string uses the counted count of the common buffer under the cover. When the line is changed, the implementation will carefully check whether the buffer is currently being shared, and if so, copy it before modifying it, ensuring that the new line using this buffer will not be affected by the new record (thus name, copy when recording).

Now, with your evil program, you get access to the shared buffer through the const method (promising not to change anything), but you are changing it!

Note that with an MSVC implementation that does not use Copy On Write, the behavior will be different ( "Hello, World!" Will print correctly).

This is exactly the essence of Undefined Behavior .

+13
source

To change a const object essentially by discarding its constant using const_cast , this is Undefined Behavior .

string :: c_str () returns const char * , i.e.: pointer to a constant string c-style. Technically, changing this will result in Undefined Behavior.

Note that using const_cast is when you have a const pointer for non-constant data, and you want to change mutable data.

+5
source

Simple casting will not lead to undefined behavior. However, there will be a change in the data pointed to. ( Also see ISO 14882: 98 5.2.7-7 ).

If you want a pointer to mutable data, you can have

 std::vector<char> wtf(str.begin(), str.end()); char* lol= &wtf[0]; 
+4
source

std::string manages its own memory, so it returns a pointer to this memory directly, as with the c_str() function. It guarantees that it will be constant so that your compiler warns you if you try to modify it.

Using const_cast in this way literally discards such security and is only acceptable practice if you are absolutely sure that the memory will not be changed.

If you cannot guarantee this, you must copy the string and use a copy; it's definitely a lot safer to do it anyway (you can use strcpy ).

+2
source

See the C ++ reference link:

 const char* c_str ( ) const; 

"Creates a zero-terminated sequence of characters (c-string) with the same contents as a string object, and returns it as a pointer to an array of characters.

A trailing null character is automatically added.

The returned array indicates the internal location with the required storage space for this sequence of characters plus its terminating null character, but the values ​​in this array should not be changed in the program and guaranteed that they will remain unchanged until the next call to the mutable member function string object.

+2
source

Yes, it will cause danger because

  • input indicates that c_str happening right now, but if some_text ever changes or leaves, you will be left with a pointer pointing to the garbage. The value of c_str guaranteed to be valid only until the string changes. And even formally, only if you do not call c_str() on other lines.
  • Why do you need to cast const? You don't plan on writing to *input , do you? This is no no!
+1
source

This is very bad. See what std :: string :: c_str () does and agrees with me.

Secondly, think about why you need non-constant access to the internal functions of std :: string. Obviously you want to change the contents, because otherwise you would use a const char pointer. You are also worried that you do not want to change the original string. Why not write

 std::string input( some_text ); 

Then you have std :: string with which you can interact without affecting the original, and you have the std :: string function instead of working with an unprocessed C ++ pointer ...

+1
source

Another turning point is that it makes code extremely difficult to maintain. Example: a few years ago I had to reorganize some code containing long functions. The author wrote function signatures for accepting constant parameters, but then const_cast used them in functions to remove constants. This violated the implied warranty given by the function and made it very difficult to find out if the parameter inside the rest of the code had changed or not changed.

In short, if you have control over a string and you think you need to change it, make it non-constant first. If you do not, you will have to take a copy and work with it.

+1
source

This is UB. For example, you can do something like this:

 size_t const size = (sizeof(int) == 4 ? 1024 : 2048); int arr[size]; 

without any throws, and the compiler will not report an error. But this code is illegal. The moral is that you need to take action into account each time.

+1
source

All Articles