В чем принципиальное отличие, если оно есть, между С++ 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
необходимо назначить смежно.