web-dev-qa-db-ja.com

C ++で入れ子になったクラスで余分なパディングを避けるための賢い方法はありますか?

これらの構造体、_align1_および_align2_は同じデータを含みますが、_align1_は入れ子になったレイアウトのためにパディングが多くあります。 _align2_のようなネストされた構造体を使用している間に、_align1_のメモリ保存の整列を得るにはどうすればよいですか。

_int main() {
    struct align1 {
        struct {
            double d;    // 8 bytes
            bool b1;    //+1 byte (+ 7 bytes padding) = 16 bytes
        } subStruct;
        bool b2;        //+1 byte (+ 7 bytes padding) = 24 bytes
    };
    struct align2 {
        double d;        // 8 bytes
        bool b1, b2;    //+2 byte (+ 6 bytes padding) = 16 bytes
    };

    std::cout << "align1: " << sizeof(align1) << " bytes\n";    // 24 bytes
    std::cout << "align2: " << sizeof(align2) << " bytes\n";    // 16 bytes

    return 0;
}
_

ネストされたsubStruct構造体は外部に宣言/定義される予定です。私はC++ 17Visual Studio 2017を使用しています。

結果のコードは地獄のように汚れたり悪いことに見えたりすることができます。設定を変更するときに後でランダムなエラーを鳴らしたり休憩したりしたくないだけです。

12
Devyy

C++ 11は、使用できるキーワード「Aligna」を導入しました。( https://en.cppreference.com/w/cpp/language/alignas ))

0
Ingve Morten

あなたの問題が埋め込まれているとき、あなたの答えは#pragma pack

#プラグマパック効果

それは--[〜#〜] MSVC [〜#〜](それが発明された場所)およびまた[〜#〜]) GCC [〜#〜](MSVC CodeBaseとの互換性のために追加された場合)。

アライメントをめちゃくちゃにすることは非常にひどく終わることができます。奇数(それらのために)バイトにマルチバイトメンバを置くことで、実行時のスローダウンが発生します。つまり、CPUがすべての段階的な操作をサポートしている場合の緊張のシナリオでは、まったく整列されていない操作をサポートしています。悪い場合では、それは完全にクラッシュします(afaikはそれらをSSE命令またはx86以外のRISC CPU)に渡されようとしています)。

#pragma pack(1)の唯一の正当な使用は、私が個人的に知っていることを知っています。他方は、@ ALTYが言及したギガバイトサイズの配列のような本当に大きなデータ構造になります。

より大きな絵では、パディングはタイムメモリトレードオフです。整列された変数にアクセスすることに保存されたCPU時間は、圧倒的多数の場合、無駄なバイトの価値があります。両方のアプローチの重大なプロファイリングなしに先に進むことはほとんどないので、あなたはそれを変える本当に良い理由が必要です。

0
Agent_L