& # 8220; & Надлежащее # 8221; способ хранения двоичных данных с помощью C ++ / STL

StackOverflow https://stackoverflow.com/questions/441203

  •  22-07-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

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

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

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

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

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

Другие советы

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top