“適切な” C ++ / STLでバイナリデータを保存する方法
-
22-07-2019 - |
質問
一般に、C ++でバイナリデータを保存する最良の方法は何ですか?私が知る限り、オプションは文字列またはベクター< char>を使用することにほとんど要約されます。 (特にC ++を参照しているため、char *とmalloc()の可能性は省略します。)
通常は文字列を使用しますが、欠落しているオーバーヘッドや、バイナリデータの健全性を損なう可能性のあるSTLが内部的に行う変換があるかどうかはわかりません。誰かがこれについてのポインタ(har)を持っていますか?提案や好みはどうですか?
解決
charのベクトルは、メモリが連続しているため便利です。したがって、バークリーソケットやファイルAPIなどの多くのC APIで使用できます。たとえば、次のことができます。
std::vector<char> vect;
...
send(sock, &vect[0], vect.size());
これで問題なく動作します。
基本的に、他の動的に割り当てられたcharバッファーと同様に扱うことができます。マジックナンバーやパターンを探して上下にスキャンできます。部分的に解析できます。ソケットから受信する場合、非常に簡単にサイズを変更してより多くのデータを追加できます。
欠点は、サイズ変更がひどく効率的ではない(サイズ変更または慎重に事前に割り当てられる)ことであり、アレイの前面からの削除も非常に効率的ではありません。たとえば、非常に頻繁に一度に1つまたは2つの文字だけをデータ構造の前面からポップする必要がある場合は、この処理の前にdequeにコピーすることもできます。これにはコピーのコストがかかり、両端キューメモリは連続していないため、C APIにポインタを渡すことはできません。
一番下の行では、データ構造とそのトレードオフについて学習してから飛び込みますが、一般的にcharのベクトルは一般的な慣習で使用されるものです。
他のヒント
std :: stringの最大の問題は、現在の標準が基礎となるストレージが連続していることを保証していないことです。ただし、文字列が連続していない既知のSTL実装はないため、実際にはおそらく失敗しません。実際、新しいC ++ 0x標準は、std :: stringがstd :: vectorなどの連続したバッファを使用するように義務付けることにより、この問題を修正しようとしています。
文字列に対するもう1つの引数は、その名前が、バイナリバッファではなく文字列を含むことを示唆していることです。
とはいえ、ベクターもお勧めします。
これにも std :: string
を使用しますが、これまでに問題が発生したことはありません。
1つの&quot;ポインター、&quot;昨日、コードの一部で鋭いリマインダーを受け取りました。バイナリデータのブロックから文字列を作成するときは、<ではなく、 std :: string(startIter、endIter)
コンストラクターフォームを使用code> std :: string(ptr、offset、length)形式-後者は、ポインターがCスタイルの文字列を指していると仮定し、最初のゼロ文字以降は無視します(&quot; up length
文字ではなく、指定された length
に)。
確かにcharのコンテナを使用する必要がありますが、使用するコンテナはアプリケーションによって異なります。
Charsには、バイナリデータを保持するのに役立ついくつかのプロパティがあります。標準では、「パディング」は許可されません。 charデータ型の場合、これはバイナリレイアウトにゴミが入らないことを意味するため重要です。また、各文字は正確に1バイトであることが保証されており、幅が設定された唯一の単純な古いデータ型(POD)になります(他のすべては上限および/または下限で指定されます)。
文字を格納する適切なstlコンテナに関する議論は、上記のDougによってうまく処理されています。どちらが必要かは、ユースケースに完全に依存します。特別なルックアップ、追加/削除、またはスプライスを必要とせずに、繰り返し処理するデータのブロックを保持している場合は、多くのライブラリと関数が想定するstd :: stringよりも意図を明確にするベクトルを優先しますnullで終わるcスタイルの文字列を保持します。