Преимущества вектора <char> по строке?
Этот вопрос связан, но не совсем так, как этот вопрос.
Есть ли какие-либо преимущества при использовании std::vector<char>
вместо std::string
для хранения произвольных двоичных данных в сторону из проблем, связанных с читабельностью?
то есть. Есть ли какие-либо задачи, которые проще/эффективнее/лучше выполнять вектор с по сравнению со строкой?
Ответы
Ответ 1
Да, vector<char>
действительно имеет больше возможностей по сравнению со string
.
В отличие от string
, vector<char>
гарантированно сохраняет итераторы, ссылки и т.д. Во время операции swap
. Смотрите: Может ли std::vector
использовать небольшую оптимизацию буфера?
Ответ 2
Помимо читаемости (которую нельзя недооценивать), я могу вспомнить пару незначительных проблем с производительностью/памятью с использованием std::string
over std::vector
:
-
В некоторых современных реализациях std::string
используется небольшая оптимизация строк. Если вы храните данные, превышающие внутренний буфер string
, он становится пессимизацией, снижая эффективность копирования, перемещения и swap
1 и увеличивая sizeof()
без выгоды.
-
Эффективная реализация std::string
всегда будет выделять как минимум еще 1 байт, чем текущий размер для хранения завершающего нуля (для этого не требуется дополнительная логика в operator[]
, чтобы справиться с str[size()]
).
Я должен подчеркнуть, что оба эти вопроса очень незначительны; стоимость их работы, скорее всего, будет потеряна при фоновом шуме. Но вы спросили.
1 Эти операции требуют разветвления на size()
, если используется оптимизация небольших строк, тогда как они не имеют хорошей реализации std::vector
.
Ответ 3
Помимо читаемости и обеспечения того, что другой сопровождающий не путает цель std::string
, в функции не так много разницы. Разумеется, вы можете рассмотреть char */malloc, если эффективность является единственным соображением.
Одна потенциальная проблема, о которой я могу думать:
std::string
по умолчанию сохраняется <char>
. Если позже вам понадобится обращаться с другим типом (например, без знака), вам может понадобиться:
- Создайте свой собственный typedef
std::basic_string<unsigned short>
(который отводит вас от нормальной обработки std::string
)
- Предварительно примените некоторую логику reinterpret_cast в сеттере.
С помощью вектора вы можете просто изменить контейнер на std::vector<unsigned short>
.
Ответ 4
Я думаю, что единственное преимущество, которое вы могли бы выиграть от этого, - это простота приращения над символами std::vector
, но даже это можно сделать с помощью std::string
.
Вы должны помнить, что даже если std::string
похоже на объект, к нему можно получить доступ, как к массиву, поэтому даже доступ к определенным частям строки может быть выполнен без использования std::vector
Ответ 5
В идеале можно было бы использовать vector<unsigned char>
для хранения произвольных двоичных данных, но я думаю, вы уже это знали, поскольку вы ссылались на старый вопрос.
Кроме того, использование вектора определенно будет более эффективным с точки зрения памяти, поскольку строка добавит завершающий символ Nul. Производительность также может улучшиться по мере того, как механизм распределения отличается для обоих - векторы гарантируют непрерывную память!
Кроме того, использование строки неверно, поскольку вызывающие/пользователи могут непреднамеренно ссылаться на некоторые из строковых методов, что может быть катастрофой.
Ответ 6
Как отмечают другие ответы, вектор может быть несколько быстрее, поскольку он гарантирует непрерывную память даже для небольших размеров и не добавляет в конец лишний нулевой байт. Тем не менее, гораздо проще (с точки зрения кода) объединить две строки, чем объединить два вектора:
Используя vector
:
vector<char> a, b;
// ...
vector<char> c;
c.insert(c.end(), a.begin(), a.end());
c.insert(c.end(), b.begin(), b.end());
Используя string
:
string a, b;
// ...
string c = a + b;