OK, so: we all know that generally the use of const_cast<>()
anywhere is so bad it’s practically a programming war crime. So this is a hypothetical question about how bad it might be, exactly, in a specific case.
To wit: I ran across some code that did something like this:
std::string temporary = "/tmp/directory-XXXXX";
const char* dtemp = ::mkdtemp(const_cast<char*>(temporary.c_str()));
/// `temporary` is unused hereafter
… now, I have run across numerous descriptions about how to get writeable access to the underlying buffer of a std::string
instance (q.v. https://stackoverflow.com/a/15863513/298171 for example) – all of them have the caveat that yes, these methods aren’t guaranteed to work by any C++ standard, but in practice they all do.
With this in mind, I am just curious on how using const_cast<char*>(string.c_str())
compares to other known methods (e.g. the aforementioned &string[0]
, &c)… I ask because the code in which I found this method in use seems to work fine in practice, and I thought I’d see what the experts thought before I attempt the inevitable const_cast<>()
-free rewrite.
const
cannot be enforced at hardware level because in practice, in non-hypothetical environment, you can set read-only attribute only to a full 4K memory page and there are huge pages on the way, which drastically reduce CPU's lookup misses in the TLB.
const
doesn't affect code generation like __restrict
from C99 does. In fact, const
, roughly speaking, means "poison all write attempts to this data, I'd like to protect my invariants here"
Since std::string
is a mutable string, its underlying buffer cannot be allocated in read-only memory. So const_cast<>
shouldn't cause program crash here unless you're going to change some bytes outside of underlying buffer's bounds or trying to delete
, free()
or realloc()
something. However, altering of chars in the buffer may be classified as invariant violation. Because you don't use std::string
instance after that and simply throw it away this shouldn't provoke program crash unless some particular std::string
implementation decide to check its invariants' integrity before destruction and force a crash if some of these are broken. Because such check couldn't be done in less than O(N) time and std::string
is a performance critical class, it is unlikely to be done by anyone.
Another issue may come from Copy-on-Write strategy. So, by modifying the buffer directly you may break some other std::string
's instance which shares the buffer with your string. But few years ago majority of C++ experts came to conclusion that COW is too fragile and too slow especially in multi-threaded environments, so modern C++ libraries shouldn't use it and instead adhere to using move construction where possible and avoiding heap traffic for small length strings where applicable.