std :: string или std :: vector <char>для хранения необработанных данных - PullRequest
6 голосов
/ 09 марта 2012

Надеюсь, этот вопрос подходит для стекового потока ... В чем разница между сохранением необработанных байтов данных (8 бит) в std::string, а не в std::vector<char>. Я читаю двоичные данные из файла и храню эти необработанные байты в std::string. Это хорошо работает, нет проблем или проблем с этим. Моя программа работает как положено. Однако другие программисты предпочитают подход std::vector<char> и предлагают прекратить использование std::string, поскольку это небезопасно для необработанных байтов. Поэтому мне интересно, почему небезопасно использовать std::string для хранения необработанных байтов данных? Я знаю, что std::string чаще всего используется для хранения текста ASCII, но байт - это байт, поэтому я не понимаю предпочтения std::vector<char>.

Спасибо за любой совет!

Ответы [ 3 ]

13 голосов
/ 09 марта 2012

Проблема не в том, работает ли он или нет.Проблема в том, что следующий парень, который читает ваш код, очень запутан.std::string предназначен для отображения текста.Любой, кто читает ваш код, будет ожидать этого.Вы объявите свое намерение намного лучше с std::vector<char>.

. Это увеличивает ваш WTF / мин в обзорах кода.

5 голосов
/ 09 марта 2012

В C ++ 03 использование std::string для хранения массива байтовых данных не было хорошей идеей.По стандарту std::string не не имеет для непрерывного хранения данных.C ++ 11 исправил это так, что его данные должны быть смежными.

Так что в C ++ 03 это было бы не функционально.Если только вы лично не проверили реализацию стандартной библиотеки C ++ на std::string, чтобы убедиться, что она непрерывна.

В любом случае, я бы предложил vector<char>.Обычно, когда вы видите string, вы ожидаете, что это будет ... строка.Вы знаете, последовательность символов в той или иной форме кодирования.vector<char> делает очевидным, что это не строка, а массив байтов.

3 голосов
/ 05 апреля 2014

Помимо смежных проблем хранения и ясности кода, я столкнулся с некоторыми довольно коварными ошибками, пытаясь использовать std::string для хранения необработанных байтов.

Большинство из них были сосредоточены на попытке преобразовать массив байтов char в std::string при взаимодействии с библиотеками Си. Например:

std::string password = "pass\0word";
std::cout << password.length() << std::endl; // prints 4, not 9

Может быть, вы можете исправить это, указав длину:

std::string password("pass\0word", 0, 9);
std::cout << password.length() << std::endl; // nope! still 4!

Вероятно, это связано с тем, что конструктор ожидает получения C-строки, а не байтового массива. Возможно, есть лучший способ, но я закончил с этим:

std::string password("pass0word", 0, 9);
password[4] = '\0';
std::cout << password.length() << std::endl; // hurray! 9!

Немного неуклюже. К счастью, я нашел это в модульном тестировании, но я бы пропустил его, если бы в моих тестовых векторах не было нулевых байтов. Что делает это коварным, так это то, что второй вышеописанный подход будет работать нормально , пока массив не будет содержать нулевой байт.

Пока что std::vector<uint8_t> выглядит хорошим вариантом (спасибо Дж. Н. и Хюркилу):

char p[] = "pass\0word";
std::vector<uint8_t> password(p, p, p+9); // :)

Примечание. Я не пробовал конструктор итератора с std::string, но эта ошибка достаточно проста, чтобы ее можно было избежать даже при такой возможности.

Извлеченные уроки:

  • Методы обработки тестовых байтов с тестовыми векторами, содержащими нулевые байты.
  • Будьте осторожны, когда (и я бы сказал, избегать) использовать std::string для хранения необработанных байтов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...