Вектор против строки

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

Обратите внимание, что этот ответ написан на С++ 11, поэтому string необходимо назначить смежно.