Apart from the reasons posted here there is also another one - binary compability. Libraries' writers have no control over which std::string
implementation you are using and whether it has the same memory layout as theirs.
std::string
is a template, so its implementation is taken from your local STL headers. Now imagine that you are locally using some performance-optimised STL version, fully compatible with the standard. For example, you may have chosen to intrudce static buffer in each std::string
to reduce the number of dynamic allocations and cache misses. As a result, memory layout and/or size of your implementation is different than library one's.
If only the layout is different, some std::string
member function calls on instances passed from library to the client or the other way around may fail, dependending on which members were shifted.
If the size is different as well, all library types having std::string
member will appear to have different sizeof when checked in the library and in the client code. Data members following std::string
member will have offsets shifted as well, and any direct access/inline accessor called from the client will return rubbish, despite "looking OK" when debugging the library itself.
Bottomline - if library and the client code are compiled agains different std::string
versions, they will link just fine, but it may result in some nasty, hard to understand bugs. If you change your std::string
implementation all libraries exposing members from STL have to be recompiled to match the client's std::string
layout. And because programmers want their libraries to be robust you'll rarely see std::string
exposed anywhere.
To be fair, this applies to all STL types. IIRC they don't have standarised memory layout.
java.lang.String
(lack of operator overloading, etc.) would make it a pain to use anything else.