Вектор против строки - PullRequest
       5

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

18 голосов
/ 29 декабря 2010

В чем принципиальная разница, если таковая имеется, между C ++ std :: vector и std :: basic_string?

Ответы [ 7 ]

19 голосов
/ 29 декабря 2010
  • basic_string не вызывает конструкторы и деструкторы своих элементов.vector делает.

  • подкачка basic_string делает недействительными итераторы (включение оптимизации небольших строк), подстановка векторов - нет.

  • basic_string память не может быть выделенапостоянно в C ++ 03.вектор всегда непрерывен.Это различие устранено в C ++ 0x [string.require]:

    Символьные объекты в объекте basic_string должны храниться непрерывно

  • basic_string имеет интерфейс для строковых операций.vector not.

  • basic_string может использовать стратегию копирования при записи (в до C ++ 11).вектор не может.

Соответствующие кавычки для неверующих:

[basic.string]:

Шаблон класса basic_string соответствуеттребованиям к контейнеру последовательностей (23.2.3), к обратимому контейнеру (23.2) и к контейнеру, поддерживающему Allocator (таблица 99), за исключением того, что basic_string не создает и не уничтожает свои элементы с использованием allocator_traits :: construct и allocator_- traits :: destroy, и этот swap () для basic_string делает недействительными итераторы.Итераторы, поддерживаемые basic_string, являются итераторами с произвольным доступом (24.2.7).

12 голосов
/ 29 декабря 2010

basic_string дает реализации компилятора и стандартной библиотеки, несколько свобод по сравнению с вектором:

  1. «Оптимизация небольших строк» ​​действительна для строк, что позволяет реализациям хранить в строке объект фактической строки, а не указатель на строку, когда строка короткая. Что-то вроде:

    class string
    {
        size_t length;
        union
        {
            char * usedWhenStringIsLong;
            char usedWhenStringIsShort[sizeof(char*)];
        };
    };
    
  2. В C ++ 03 базовый массив не обязательно должен быть смежным. Реализация basic_string в виде чего-то вроде «веревки» была бы возможна в соответствии с действующим стандартом. (Хотя никто не делает этого, потому что это сделает члены std::basic_string::c_str() и std::basic_string::data() слишком дорогими для реализации.)
    C ++ 11 теперь запрещает такое поведение.

  3. В C ++ 03 basic_string позволяет поставщику компилятора / библиотеки использовать копирование при записи для данных (которое можно сохранять при копировании), что недопустимо для std::vector. На практике это было гораздо более распространенным явлением, но в настоящее время оно встречается реже из-за влияния, которое оно оказывает на многопоточность. В любом случае, ваш код не может полагаться на то, реализован ли std::basic_string с помощью COW.
    C ++ 11 снова запрещает это поведение.

Есть также несколько вспомогательных методов, привязанных к basic_string, но большинство из них просты и, конечно, могут быть легко реализованы поверх vector.

6 голосов
/ 29 декабря 2010

Ключевым отличием является то, что 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

На практике это различие не так важно.

0 голосов
/ 22 февраля 2016

TLDR: string s оптимизированы, чтобы содержать только символьные примитивы, vector s может содержать примитивы или объектов

Выдающаяся разница между vector и string составляетчто vector может правильно содержать объекты, string работает только на примитивах.Поэтому vector предоставляет следующие методы, которые были бы бесполезны для string, работающего с примитивами:

  1. vector :: emplace
  2. vector:: emplace_back
  3. vector :: ~ vector

Даже расширение string не позволит ему правильно обрабатывать объекты, поскольку в нем отсутствует деструктор,Это не следует рассматривать как недостаток, оно позволяет значительно оптимизировать по сравнению с vector в том смысле, что string может:

  1. Do оптимизация коротких строк , потенциально избегая выделения кучи, с little до без увеличения объема памяти
  2. Используйте 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 that:

  1. Будут использоваться только типы примитивов char, wchar_t, char16_t или char32_t. Очевидно, что примитивы размером до 32-битных, могут используйте их эквивалентные размеры char_type: https://stackoverflow.com/a/35555016/2642059, но для таких примитивов, как long long, необходимо написать новую специализацию char_traits и идею специализации char_traits::eof и char_traits::not_eof вместоиспользование vector<long long> не кажется лучшим использованием времени.
  2. Из-за оптимизации коротких строк итераторы становятся недействительными для всех операций, которые делают недействительным итератор vector, но итераторы string дополнительноаннулируется string::swap и string::operator=

Дополнительные различия в интерфейсах vector и string:

  1. Не существует изменяемого string::data: Почему std :: string.data () не предоставляет изменяемый символ *?
  2. 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
  3. Наконец везде vector принимает аргументы другого vector, string принимает string или a char*

Обратите внимание, этот ответ написан против C ++11, поэтому string s должны быть распределены непрерывно.

0 голосов
/ 08 июля 2014

Разница между std::string и std::vector в том, что программы могут создавать строку из строки с нулевым символом в конце, тогда как с векторами они не могут.

std::string a = "hello";          // okay
std::vector<char> b = "goodbye";  // compiler error

Это часто облегчает работу со строками.

0 голосов
/ 29 декабря 2010

basic_string предоставляет множество специфичных для строки опций сравнения. Вы правы в том, что базовый интерфейс управления памятью очень похож, но строка содержит много дополнительных членов, таких как c_str (), которые не имеют смысла для вектора.

0 голосов
/ 29 декабря 2010

Вектор - это структура данных, которая имитирует массив. Глубоко внутри это фактически (динамический) массив.

Класс basic_string представляет последовательность символов. Он содержит все обычные операции последовательности и, кроме того, он содержит стандартные строковые операции, такие как поиск и объединение.

Вы можете использовать вектор для сохранения любого типа данных, который вы хотите std::vector<int> or <float> or even std::vector< std::vector<T> >, но basic_string можно использовать только для представления "текста".

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...