6

std::pair をバイナリ ファイルに保存しようとすると、不快なことが 1 つあることに気付きました。プロセッサ効率の面では便利かもしれませんが、より多くのストレージ スペースが必要になるため、std::pair のアライン モードを 1 バイトに切り替えたいと考えています。私のコンパイラは MS VC++ 2012 です。

#include <iostream>

int main( )
{
    struct S_a { double a; size_t b; };

#pragma pack(1)
    struct S_wa { double a; size_t b; };

    std::cout << sizeof( size_t ) << '\n';                          // 4
    std::cout << sizeof( double ) << '\n';                          // 8
    std::cout << sizeof( std::pair< size_t, size_t > ) << '\n';     // 8
    std::cout << sizeof( std::pair< double, size_t > ) << '\n';     // 16 - bad
    std::cout << sizeof( S_wa ) << '\n';                            // 12 - good
    std::cout << sizeof( S_a ) << '\n';                             // 16
    std::cout << sizeof( std::pair< double, double > ) << '\n';     // 16
}

私はこれを試しましたが、うまくいきません:

#pragma pack(1)
    typedef std::pair< double, size_t > Q;

    std::cout << sizeof( Q ) << '\n';                               // 16
4

3 に答える 3

6

Astd::pairは基本的に次のように縮小されます。

class xxx
{
   T1 _t1;
   T2 _t2;
};

2 つのメンバーの配置は、インスタンスのインスタンス化に使用されるときだけでなく、テンプレート自体が定義されるときに有効な配置によって定義されます。

STL の Microsoft 実装では、シンボル_CRT_PACKINGを使用して、すべての STL コンポーネントに使用されるパッキングを定義します。デフォルトでは、パッキングは 8 に設定されています。std::pair( <utility>) を定義するヘッダーを含める前にこのシンボルを自分で定義すると、理論的にはパッキングをオーバーライドして独自に設定できます。

標準のパッキングを想定しているライブラリやその他のコードを呼び出すときに発生する可能性がある潜在的な問題に注意してください。

于 2013-08-16T04:17:09.130 に答える
4

申し訳ありませんpackが、この状況ではプラグマは機能しません。あなたは出来る

#define _CRT_PACKING 1
#include <utility>

これはあらゆる種類の問題を引き起こす可能性があります。その 1 つは、特定の API、特に低レベルの API が、データが特定の方法で整列されることを期待することです。それらのすべてが、そうでない状況に対処できるほど賢いわけではありません。不意のクラッシュにつながる可能性があります。

オブジェクトをこのようにシリアル化する必要がある場合は、std::pair<U,V>自分でシリアル化を処理します (例のみ)。

template<typename U, typename V>
void paircpy(char *dest, const std::pair<U, V> &pair) {
    memcpy(buffer, &pair.first, sizeof(U));
    memcpy(buffer + sizeof(U), &pair.second, sizeof(V));
}

うまくいかないデータ型の特殊なケースを処理する必要がありmemcpyます。

深刻なプロジェクトでは、オブジェクトを移植可能な方法でシリアル化して、浮動小数点、署名付きデータ型のさまざまなエンコーディング、ポインター、配列、STL コンテナーなどをエレガントに処理できるようにする必要があります。オブジェクトのメモリの単純なダンプができないか、不十分です。

C++の FAQ を読んで、オブジェクトのメモリ内表現をファイルにダンプする以上の独自のシリアライゼーション モジュールを開発してください。

または、事前にパッケージ化されたポータブル ソリューションを使用して、次のようなデータ型をシリアル化することもできます。

于 2013-08-16T04:25:11.160 に答える
0

わかりました、まったく異なる「解決策」ですが、それは良い考えかもしれませんし、そうでないかもしれません。他の回答と同じ注意事項がすべて付属していますが、毒を選んで選択することができます.

std::pairその特定の定義のプラグマパックを使用して、関心のある型の部分的な特殊化を行います。charint: _

namespace std {
#pragma pack( /* ... whatever you want ... */ )
template<> struct pair<char,int> {
  char first;
  int second;
};
}

どこかに触れることができる定義により、パッキングに影響を与えることができます。繰り返しますが、これは、関連するすべてのタイプに対して実行する意思がある場合にのみ有効であり、他のポスターで言及されている警告に留意してください。

使用しているライブラリがクレイジーで、残りのライブラリが依存するものをさらに追加することにした可能性はわずかですがpair、おそらく心配する必要はありません

于 2013-08-16T04:44:46.813 に答える