The history of those demonstrate some of the bat-shit insanity of the evolution of C++. Originally data didn't have to null-terminated, but then they finally realized that making c_str actually work without this invariant in general was nearly impossible. So since C++11 data and c_str are equivalent.
Edit: by impossible I really mean something usable with sane complexity requirements -- that wouldn't make people just immediately discard std::string for something better. This is the same C++ that brought you auto_ptr, and other garbage. C++11 corrected many things, this included.
NUL-terminated strings were one of the dumber things C++ inherited from C, and code that depends on NUL termination is not a thing to be proud of.
Basically the NUL-terminator amounts to a 1-byte of wasted space -- which is almost always completely in the noise -- if you're using std::string for tiny strings you're paying at least 24 bytes anyway. There are just very few cases where that one extra byte matters.
I think the overwhelming opinion is that this 1-byte trade-off is better than the overhead of allocation and copying when you want to pass that string around. NUL-terminated strings aren't important in C++ because of C (well, not directly), but because they are essentially the ABI of countless existing libraries and the major operating systems.
> code that depends on NUL termination is not a thing to be proud of.
Whatever. Code that depends on NUL termination is ubiquitous.
You have not thought it through. There was always space for a NUL, but nobody needs it to have a NUL in it until somebody calls c_str(). Anyway, that was true until somebody jiggered the Standard, just before 1998, to require a NUL visible to s[s.size()].
>C Code that depends on NUL termination is ubiquitous.
Fixed that for you.
No.
This is not technically true. You could plugin your hated NUL byte in the implementation of operator [].
> C Code that depends on NUL termination is ubiquitous.
No, that's not what I said. It really doesn't matter what language underlying the API of all the code that expects NUL terminated strings is written in (a lot of it is C++ of course too). Windows, MacOS, and all POSIX-ish systems have a large API that consumes NUL terminated strings. NUL terminated strings are ubiquitous in computing at this point. Sure blame C from 40 years ago and burn a dmr effigy, I don't care, but that battle was long lost.
NUL terminated strings may be terrible, but the C++ accomodation for them is not -- its a well-thought out trade-off. My understanding is that neither go nor Rust make this trade-off. golangs FFI and syscall overhead has always been something of a performance disaster anyway. C++ has always had a greater demand to "play nice" with legacy code and systems then either of those.
The overhead of just having the NUL-byte is almost always a non-factor. If it really is, then use a byte vector.
If you think anybody is complaining about the extra space for the NUL, what you are barking up is not even a tree.
> Evidently that is a minority preference.
What evidence? Pointing out a fact isn't an endorsement.
> If you think anybody is complaining about the extra space for the NUL
Then what exactly are you complaining about? Setting the byte to 0? If not, why are you being so obtuse?
> what you are barking up is not even a tree.
In this thread your tone is repeatedly that of a condescending jerk.
[1] with a compiler flag use_cxx11_abi=0 or something