3

C++ で永続的なデータ構造を書こうとしていますが、データ構造リーダーの他のさまざまな実装とバイナリ互換にすることができるはずだと感じているため、現在の考えは、抽象化せずにネイティブ メモリでデータ構造を宣言することです。 .

たとえば、メモリの線形ブロックを (newキーワードを使用して) データ構造として指定し、最初のバイトの意味、2 番目のバイトの意味などを記述します。を使用してこれを行うことができることはわかっていますstructが、データ構造は1つの言語にバインドされ、他の言語はこの構造を使用する必要があります。また、実装はコンパイラごとに変わる可能性があります。代わりに、メモリの標準として使用したいと思います。

私がやろうとしていることはやや賢明ですか?それとも、物事を単純化しすぎて、本当にstructデータ構造を進める必要がありますか? C++ の部分に移りましょう。データ構造を使用する必要があると思われる場合struct、本格的なクラスを使用することの欠点は何ですか?

(データ構造はとにかく永続であるため、とにかくクラスを使用してメモリ構造をラップし、関数を提供しています。 )クラスラッパーについては適切に述べられていません。つまり、メモリ表現用のクラス インターフェイスが必要であり、必ずしもラッパーである必要はありません。

4

2 に答える 2

1

私が読んだり操作したりしたいくつかのファイル形式は、まさにそれを行います-メモリ標準またはレイアウトを定義し、通常、C に似た擬似的なデモでそれをバックアップしstructます。構造体やクラスの表現を提供するものもあれば、ライブラリによって完全に抽象化されたものもあります。もちろん、これらのフォーマットは、すべてのフィールド、それらのサイズ、データのエンディアンなどを文書化します。

エンディアン関連の問題、パディング、複雑さ (たとえば、データ構造のバリエーションによって導入される)、および適切なバージョン管理が、エラーの最大の原因であると考えています。私が見つけたもう1つの問題は、過去のデータ構造の使用と、同様の機能を表すために使用されるデータ構造の不一致です.仕様を受け取って、いくつかの異なる文字列表現が含まれていることに気付くかもしれません.これらすべてを (双方向で) サポートし続けます。

そのルートを進める:

サポートしたくない場合は、バイナリ表現 (またはコンパイル可能なプログラム) にコミットするべきではありません (また、プラットフォームやツールセットが変更されるため、長期的な形式の試みは途中で失敗/つまずきます)。最初に正式なメモリ標準にコミットし、その上にテストと入力ファイルの例を作成して、表現が正しくシリアル化および逆シリアル化されていることを確認します。非常に基本的なテスト スイートは、モデルが必要なすべてのシステムで移植可能であることを確認するのに役立ち、潜在的な落とし穴や、気付いていないプラットフォーム固有の考慮事項を指摘することができます。

コンパイル可能な表現を本当に提供したい場合は、非常に準拠したstruct表現に固執します。クライアントはその (メモリ内の) 表現を取得して、好きな C++ 抽象化/表現に変換できます。つまり、シリアル化された表現は、自明な単純な表現とそのような表現の中間ストレージ (フラット化およびパックされた構造体) を除いて、おそらくメモリ内の表現を反映するべきではありません。

重要な部分の 1 つは、これらの構造体を使用して作成したメモリ内オブジェクト グラフが、順方向および逆方向のシリアル化および逆シリアル化が可能であり、適切なバージョン管理をサポートしていることを確認するテストを用意する必要があることです。複雑なシリアル化された表現と互換性があります。つまり、このアプローチは、1 つの抽象化レイヤーを別のレイヤーの上に導入するだけであることがわかります。この点に関して、C++ 抽象化に、パックされたメモリ表現からそれ自体を作成する機能を与え、その表現がデータを失うことなくパックされた構造に正しく移入できることを保証することが必要な場合があります。

それを超えて、より高度なインターフェースを持つ必要はありますか? ある場合は、その情報を提供することをお勧めします。

そうです、メモリ標準は、プラットフォーム/アーキテクチャの違いに関係なく、正しく安定している必要があり、すべての実装が参照してテストする必要がある部分です。IOW、あなたは正しい軌道に乗っています ;)

于 2012-09-02T02:00:15.890 に答える
0

C++ では、 と の間に実質的な違いはstructありませんclass(既定のアクセシビリティが で公開されていることを除けばstruct)。伝統的structに、型が (パブリック) メンバー変数のみを持ち、メンバー関数を持たない場合に使用されますが、これは単なる規則であり、コンパイラによって強制される規則ではありません。

データの説明には必ずstruct/classを使用します。誰かがあなたのデータ構造のリーダーを書きたい場合、ヘッダー ファイルをインポートするか、選択した言語でデータ構造を実装することができます。ほとんどのプログラミング言語では、これは非常に単純なはずです。

次のような構造を開始することをお勧めします。

typedef struct
{
    int Version; // struct layout version
    int ByteSize; // byte size of structure for validation
    ...
} MYDATA;

このようにして、データ構造が渡されるときに、コードは、割り当てられた構造のサイズが、構造の特定のバージョンに期待されるバイト数と一致することを確認できます。その後、バージョン フィールドを更新して新しいサイズを確認するだけで、構造の新しいバージョンを簡単に導入できます。

データをディスクに保存するときは、単一​​の書き込みではなく、フィールドごとに書き出すようにしてください (ポインターを使用し、sizeof()他の言語が C++ コンパイラーの潜在的なパディングを処理する必要がないようにするため)。パディングがないように手動で構造内にフィールドをレイアウトすることは可能ですが、その際には非常に注意が必要であり、間違いを犯しやすいです。

于 2012-09-02T01:35:59.487 に答える