Подтвердить что ты не робот

"Правильный" способ хранения двоичных данных с помощью С++/STL

В общем, что является лучшим способом хранения двоичных данных на С++? Параметры, насколько я могу судить, в значительной степени сводятся к использованию строк или векторов <char> s. (Я опускаю возможность char * s и malloc(), так как я имею в виду конкретно С++).

Обычно я просто использую строку, однако я не уверен, есть ли накладные расходы, которые я потерял, или преобразования, которые STL делает внутренне, что может испортить разумность двоичных данных. У кого-нибудь есть указатели (хар) по этому поводу? Предложения или предпочтения так или иначе?

4b9b3361

Ответ 1

вектор char хорош, потому что память смежна. Поэтому вы можете использовать его с большим количеством C API, таких как сокеты berkley или файловые API. Вы можете сделать следующее, например:

  std::vector<char> vect;
  ...
  send(sock, &vect[0], vect.size());

и он будет работать нормально.

Вы можете по существу относиться к нему так же, как любой другой динамически выделенный буфер char. Вы можете сканировать вверх и вниз в поисках магических чисел или паттеров. Вы можете разобрать его частично на месте. Для получения из сокета вы можете легко изменить его размер, чтобы добавить больше данных.

Недостатком является изменение размера не очень эффективно (изменение размера или предубеждение предусмотрительно), и удаление из передней части массива также будет очень неопределенным. Если вам нужно, скажем, выставить только один или два символа в момент времени перед структурой данных очень часто, копируя их в deque, прежде чем эта обработка может быть вариантом. Это стоит вам копия, а память deque не соприкасается, поэтому вы не можете просто передать указатель на C API.

Внизу, узнайте о структурах данных и их компромиссах перед погружением, однако вектор char обычно является тем, что я вижу в обычной практике.

Ответ 2

Самая большая проблема с std::string заключается в том, что текущий стандарт не гарантирует, что его базовое хранилище смежно. Однако нет известных реализаций STL, где строка не является смежной, поэтому на практике она, вероятно, не подведет. Фактически, новый стандарт С++ 0x исправит эту проблему, указав, что std::string использует непрерывный буфер, например std::vector.

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

Тем не менее, я рекомендую также вектор.

Ответ 3

Я использую std::string для этого тоже, и у меня никогда не было проблемы с ним.

Один "указатель", который вчера я получил острую напоминание в куске кода: при создании строки из блока двоичных данных используйте конструктор std::string(startIter, endIter), а не форму std::string(ptr, offset, length) последний делает предположение, что указатель указывает на строку стиля С и игнорирует что-либо после первого нулевого символа (он копирует "до" указанных символов length, а не length).

Ответ 4

Конечно, вы должны использовать контейнер char, но контейнер, который вы хотите использовать, зависит от вашего приложения.

У Chars есть несколько свойств, которые делают их полезными для хранения двоичных данных: стандарт запрещает "заполнение" для типа данных char, что важно, поскольку это означает, что вы не получите мусор в своем двоичном макете. Каждому char также гарантированно будет точно один байт, что делает его единственным простым старым типом данных (POD) с установленной шириной (все остальные указаны в терминах верхней и/или нижней границ).

Обсуждение соответствующего контейнера stl, в котором хранятся символы, хорошо описано Doug выше. Какой вам нужен, полностью зависит от вашего варианта использования. Если вы просто держите блок данных, которые вы перебираете, без какого-либо специального поиска, добавления/удаления или необходимости сплайсинга, я бы предпочел вектор, который сделает ваши намерения более ясными, чем std::string, которые многие библиотеки и функции будут считать выполненными строка c-style с нулевым завершением.