web-dev-qa-db-ja.com

「4バイトのクラス「テスター」の埋め込み」警告はどういう意味ですか?

この簡略化されたテストケースの場合:

#include <map>

class Tester {
    int foo;
    std::map<int, int> smap;
};

int main() {
    Tester test; 
    return 0;
}

次のコンパイラ警告が表示されます。

$ clang++ -std=c++98 -Weverything test.cc 
test.cc:5:24: warning: padding class 'Tester' with 4 bytes to align 'smap' [-Wpadded]
    std::map<int, int> smap;
                       ^

この警告の意味と、それに対処する方法を誰かが説明できますか?

32
Dun Peal

ここには実際の問題はありません。 CおよびC++では、コンパイラーは構造体メンバーの後にパディングを挿入してより適切な配置を提供し、より高速なメモリアクセスを可能にします。この場合、smapを8バイトアライメントに配置することを決定したようです。 intはほぼ確実に4バイトであるため、警告は、構造体の中央に4バイトの無駄なスペースがあることを示しています。

構造体のメンバーが多い場合は、定義の順序を切り替えることもできます。たとえば、Testerにメンバーがいた場合:

 struct Tester {
     int foo;
     std::map<int, int> smap;
     int bar;
 };

次に、配置を最適化して無駄なスペースを避けるために、2つのintを隣り合わせに配置することは理にかなっています。ただし、この場合、メンバーは2つしかありません。メンバーを入れ替えても、コンパイラーはおそらく、配置されたTestersの配置を最適化するために、構造体の最後に4バイトのパディングを追加します。配列内。

23
Tristan Brindle

これを64ビットシステムでコンパイルしていると思います。

64ビットシステムでは、ポインタは8バイトです。コンパイラーは構造体のメンバーを自然な境界に揃えます。そのため、8バイトのポインターは、8バイトの倍数である構造体のオフセットから始まります。

intは4バイトしかないため、コンパイラーはfooの後に4バイトの「パディング」を挿入し、smapが8バイトの境界にあるようにしました。

編集:smapはポインターではなく、std::map、同じロジックが適用されます。オブジェクトの配置の正確なルールが何かはわかりませんが、同じことが起こっています。

何をすべきか?何もない。あなたのコードは完全に素晴らしいです、コンパイラはこれが起こったことをあなたに単に知らせています。心配する必要はまったくありません。 -Weverythingは、オンにする すべての警告 をオンにすることを意味します。これは、ほとんどすべてのコンパイルでおそらく過剰です。

5

Sytsemのコンパイラは64ビットシステムにポインタを与えることを選択しました8 bytes、構造体のintは4 bytesを持っています。昔は同じような問題や警告が以前のコード例で作業していることが多いので、もっと深く掘り下げる必要がありました。

簡潔にするために、intは60年代に定義され、64ビットシステム、ギガバイトのストレージもGBのRAMも考慮されていませんでした。

エラーメッセージを解決するには、必要に応じてintではなくsize_t(size type)を使用します。map stlを使用する場合は、複数の異なるシステムで実行するようにプログラムされています。

size_tを使用すると、32ビットシステムまたは64ビットシステムまたはアームでコンパイルする場合、コンパイラーは必要なバイトサイズを自分で選択できます。メッセージが表示されなくなり、コードを変更する必要もありません。将来コードをコンパイルするシステムに関係なく。

0
Ivanovic