Ok, the reasons are/were:
1. Back in 2001-ish, Java was cool, and I was copying the java string class.
2. I wanted more functionality than std::string offers. Yes, yes, I know all the arguments about keeping the class simple and using external methods for adding functionality, and I generally agree with that philosophy, but having used both juce::String and std::string, in practice the juce design just seemed to result in cleaner code.
3. I wanted it to be able to easily cast to utf-16 or 32, and std::string was a bit clunky for that.
4. It's a long time ago, but I vaguely remember std::string having performance issues on some platforms.. Can't remember the details, but there were definitely problems that made it perform differently on different compilers.
If I was designing a string class today with hindsight, I'd probably still go for the overall design of juce::String, maybe tweaking some of the methods a bit, but I might make it wrap a std::string so that they can be interchanged efficiently.
If I was designing a string class today with hindsight, I'd probably still go for the overall design of juce::String, maybe tweaking some of the methods a bit, but I might make it wrap a std::string so that they can be interchanged efficiently.