Большая часть причин связана с локализацией и интернационализацией (L10I18), производительностью и по историческим причинам.
Для проблем L10I18 был добавлен char_traits, и вы заметите, что потоки также имеют их. Намерение состояло в том, чтобы сделать «более умных персонажей» таким образом, но результат был бесполезен. Единственное, для чего хорошо char_traits - это специализировать некоторые из сравнений, копий и т. Д. Std :: string / wstring как встроенные функции компилятора.
Ошибка в основном связана с самими потоками UNIX, которые рассматривают символ в качестве основного «атома», а в интернационализированных графических интерфейсах, сети и т. Д. Строка является основным «атомом». Другими словами, на земле C / C ++ у нас есть «немые массивы умных символов» для строк, тогда как любой другой язык использует «умные массивы немых символов». Unicode использует последний подход.
Еще одно большое различие между basic_string и vector - basic_string может содержать только типы POD. Это может иметь значение в некоторых случаях, иногда компилятору проще оптимизировать basic_string по сравнению с vector.
basic_string иногда имеет много других оптимизаций, таких как Copy on Write и Small String Optimization. Они варьируются от одной реализации к другой.
Однако, вероятно, основная причина, по которой две вещи почти одинаковы, историческая: строки предшествуют STL, и большая часть работы, кажется, сосредоточена на том, чтобы заставить их взаимодействовать с библиотекой IOStream. Один из урбанских мифов C ++ состоит в том, что STL - это «контейнерная библиотека», которая была добавлена в C ++. Это не так, и, чтобы принять его в C ++, были добавлены контейнеры. «Интерфейс STL» также был прикреплен к существующему классу строк. std :: vector был в основном взят из реализации вектора, существовавшей в AdaSTL.