Interesting article, particularly the part at the end about the new user defined literals.
The semantics between the two are indeed different. I think
std::string uses a much more sane approach. Most other languages will store string size along with a buffer pointer. It's far safer as it lets you bounds check various operations, and also allows for a number of speed improvements too. The additional cost in memory is hardly a concern these days. As far as I know, only C/C++ stored just the buffer pointer and required scanning for a sentinel value to determine string length. And it's suffered so many bugs and security flaws because of it. Not to mention frequent slow scanning to find string length, and excessive copying since you can't properly slice when a sentinel value is needed to determine an end point.
It is subtly deceptive how
std::string has a constructor to initialize it from a null terminated string. I can see that easily causing people to conflate the two. Additionally, since C++11, the
std::string is guaranteed to be null terminated. For compatibility with old code,
std::string will allocate at least 1 extra byte to ensure there is always a null just past the end of the string, though it doesn't otherwise consider null special, and can have embedded nulls which do not terminate the string.
C++ has a lot of power that can make it truly wonderful at times, but it's also damn awful in terms of legacy junk and the number of subtleties that can bite you in the butt. The newer standards go a long way towards alleviating some of the pain points, though it's not surprising when people say that's to help legacy projects, and new projects should just be written in another language.
On the plus side, you stand to learn a lot about programming and low level details of how a computer works by getting good at C++.