В чем принципиальное отличие, если оно есть, между С++ std::vector и std:: basic_string?
Вектор против строки
Ответ 1
-
basic_string не вызывает конструкторы и деструкторы своих элементов. вектор делает.
-
swapping basic_string делает недействительными итераторы (разрешая небольшую оптимизацию строк), обменивающие векторы этого не делают.
-
Базовая память basic_string не может быть выделена непрерывно в С++ 03. вектор всегда непрерывный. Эта разница удаляется в С++ 0x [string.require]:
Объекты char -like в объекте basic_string сохраняются смежно
-
basic_string имеет интерфейс для строковых операций. вектор не имеет.
-
basic_string может использовать копию в стратегии записи (в pre С++ 11). вектор не может.
Релевантные цитаты для неверующих:
[basic.string]:
Шаблон класса basic_string соответствует требованиям для контейнера Sequence Container (23.2.3), для Реверсивный контейнер (23.2) и для контейнера, поддерживающего Allocator (Таблица 99), за исключением того, что basic_string не создает и не разрушает его элементы, используя allocator_traits:: construct и allocator_- черты:: destroy и что swap() для basic_string делает недействительными итераторы. Поддерживаемые итераторы by basic_string являются итераторами произвольного доступа (24.2.7).
Ответ 2
basic_string предоставляет реализацию компилятора и стандартной библиотеки, несколько свобод над вектором:
-
"Маленькая оптимизация строк" действительна для строк, что позволяет реализациям сохранять фактическую строку, а не указатель на строку, в строчном объекте, когда строка короткая. Что-то вроде:
class string { size_t length; union { char * usedWhenStringIsLong; char usedWhenStringIsShort[sizeof(char*)]; }; }; -
В С++ 03 базовый массив не обязательно должен быть смежным. Внедрение
basic_stringс точки зрения чего-то вроде "веревки" было бы возможно в соответствии с текущим стандартом. (Хотя никто этого не делает, потому что это сделает членыstd::basic_string::c_str()иstd::basic_string::data()слишком дорогими для реализации.)
С++ 11 теперь запрещает это поведение. -
В С++ 03
basic_stringпозволяет поставщику компилятора/библиотеки использовать функцию копирования-на-запись для данных (которые могут сохранять на копиях), что не разрешено дляstd::vector. На практике это было гораздо более распространенным явлением, но в настоящее время оно менее распространено из-за воздействия, которое оно оказывает на многопоточность. В любом случае, ваш код не может полагаться на то, реализуется лиstd::basic_stringс помощью COW.
С++ 11 снова запрещает это поведение.
Есть несколько вспомогательных методов, на которые накладывается basic_string, но большинство из них просты и, конечно, могут быть легко реализованы поверх vector.
Ответ 3
Ключевым отличием является то, что std::vector должен хранить свои данные в непрерывной памяти, когда std::basic_string не смог. В результате:
std::vector<char> v( 'a', 3 );
char* x = &v[0]; // valid
std::basic_string<char> s( "aaa" );
char* x2 = &s[0]; // doesn't point to continuous buffer
//For example, the behavior of
std::cout << *(x2+1);
//is undefined.
const char* x3 = s.c_str(); // valid
Ответ 4
Вектор представляет собой структуру данных, имитирующую массив. Глубоко внутри это фактически (динамический) массив.
Класс basic_string представляет последовательность символов. Он содержит все обычные операции последовательности и, кроме того, содержит стандартные операции с строкой, такие как поиск и конкатенация.
Вы можете использовать вектор, чтобы сохранить любой тип данных, который вы хотите std::vector<int> or <float> or even std::vector< std::vector<T> >, но basic_string может использоваться только для представления "текста".
Ответ 5
Basic_string предоставляет множество вариантов сравнения по строкам. Вы правы в том, что основной интерфейс управления памятью очень похож, но строка содержит много дополнительных элементов, таких как c_str(), что не имеет смысла для вектора.
Ответ 6
Единственное различие между std::string и std::vector заключается в том, что программы могут создавать строку из строки с нулевым завершением, тогда как с векторами они не могут.
std::string a = "hello"; // okay
std::vector<char> b = "goodbye"; // compiler error
Это часто упрощает работу с цепочками.
Ответ 7
TL;DR: string оптимизированы, чтобы содержать только примитивы символов, vector может содержать примитивы или объекты
Преобладающая разница между vector и string заключается в том, что vector может корректно содержать объекты, string работает только с примитивами. Таким образом, vector предоставляет эти методы, которые были бы бесполезны для string, работающего с примитивами:
Даже расширение string не позволит ему правильно обрабатывать объекты, потому что в нем отсутствует деструктор. Это не следует рассматривать как недостаток, он позволяет значительно оптимизировать работу над vector тем, что string может:
- короткая оптимизация строк, потенциально избегая выделения кучи, немного до нет увеличенных издержек хранения
- Используйте
char_traits, один из аргументов шаблонаstring, чтобы определить, как должны выполняться операции над содержащимися примитивами (из которых реализованы толькоchar,wchar_t,char16_tиchar32_t: http://en.cppreference.com/w/cpp/string/char_traits)
Особенно важны char_traits::copy, char_traits::move и char_traits::assign, очевидно, подразумевая, что будет использоваться прямое назначение, а не строительство или уничтожение, что опять же предпочтительнее для примитивов. Вся эта специализация имеет дополнительные недостатки string, которые:
- Будут использоваться только теги
char,wchar_t,char16_tилиchar32_t. Очевидно, примитивы размером до 32 бит могут использовать их эквивалентный размерchar_type: fooobar.com/info/16873/..., но для примитивов, таких какlong long, новая специализацияchar_traitsнужно написать, а идея специализацииchar_traits::eofиchar_traits::not_eofвместо использованияvector<long long>не похоже на лучшее использование времени. - Из-за оптимизации коротких строк итераторы недействительны всеми операциями, которые сделали бы недействительным итератор
vector, но итераторыstringдополнительно недействительныstring::swapиstring::operator=
Дополнительные различия в интерфейсах vector и string:
- Нет измененного
string::data: Почему не std::string.data() предоставляет изменяемый char *? -
stringпредоставляет функциональность для работы со словами, недоступными вvector:string::c_str,string::length,string::append,string::operator+=,string::compare,string::replace,string::substr,string::copy,string::find,string::rfind,string::find_first_of,string::find_first_not_of,string::flind_last_of,string::find_last_not_of,string::operator+,string::operator>>,string::operator<<,string::stoi,string::stol,string::stoll,string::stoul,string::stoull,string::stof,string::stod,string::stold,stirng::to_string,string::to_wstring - Наконец, везде
vectorпринимает аргументы другогоvector,stringпринимаетstringилиchar*
Обратите внимание, что этот ответ написан на С++ 11, поэтому string необходимо назначить смежно.