Most of the reason has to do with localization and internationalization (L10I18),performance and for historical reasons.
For the L10I18 issues, char_traits was added, and you will note that streams has these as well. The intent was to make "smarter characters" in a way, but the outcome was useless. About the only thing char_traits is good for is to specialize some of the std::string/wstring compares, copies, etc as compiler intrinsics.
The failure is mostly due to UNIX streams themselves, which see the character as the main "atom" where in GUIs, web etc that are internationalized the string is the main "atom." In other words, in C/C++ land, we have "dumb arrays of smart characters" for strings, whereas every other language uses "smart arrays of dumb characters." Unicode takes the latter approach.
Another big difference between basic_string and vector -- basic_string can only contain POD types. This can make a difference in some cases somoetime the compiler has an easier time optimizing basic_string compared to vector.
basic_string sometimes has many other optimization, such as Copy on Write and Small String Optimization. These vary from one implementation to the next.
However probably the most reason there are two things nearly the same is historical: strings predates the STL quite a bit, and most of the work seemed to center on making them interoperate with IOStream library. One C++ Urban Myth is that STL is a "container library" that was added to C++. It is not, and to get it adopted into C++, containers were added. An "STL Interface" was also bolted onto the existing string class. std::vector was largely taken from a vector implemenation that existed in the AdaSTL.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…