この簡略化されたテストケースの場合:
#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;
^
この警告の意味と、それに対処する方法を誰かが説明できますか?
ここには実際の問題はありません。 CおよびC++では、コンパイラーは構造体メンバーの後にパディングを挿入してより適切な配置を提供し、より高速なメモリアクセスを可能にします。この場合、smap
を8バイトアライメントに配置することを決定したようです。 int
はほぼ確実に4バイトであるため、警告は、構造体の中央に4バイトの無駄なスペースがあることを示しています。
構造体のメンバーが多い場合は、定義の順序を切り替えることもできます。たとえば、Tester
にメンバーがいた場合:
struct Tester {
int foo;
std::map<int, int> smap;
int bar;
};
次に、配置を最適化して無駄なスペースを避けるために、2つのintを隣り合わせに配置することは理にかなっています。ただし、この場合、メンバーは2つしかありません。メンバーを入れ替えても、コンパイラーはおそらく、配置されたTester
sの配置を最適化するために、構造体の最後に4バイトのパディングを追加します。配列内。
これを64ビットシステムでコンパイルしていると思います。
64ビットシステムでは、ポインタは8バイトです。コンパイラーは構造体のメンバーを自然な境界に揃えます。そのため、8バイトのポインターは、8バイトの倍数である構造体のオフセットから始まります。
int
は4バイトしかないため、コンパイラーはfoo
の後に4バイトの「パディング」を挿入し、smap
が8バイトの境界にあるようにしました。
編集:smap
はポインターではなく、std::map
、同じロジックが適用されます。オブジェクトの配置の正確なルールが何かはわかりませんが、同じことが起こっています。
何をすべきか?何もない。あなたのコードは完全に素晴らしいです、コンパイラはこれが起こったことをあなたに単に知らせています。心配する必要はまったくありません。 -Weverything
は、オンにする すべての警告 をオンにすることを意味します。これは、ほとんどすべてのコンパイルでおそらく過剰です。
Sytsemのコンパイラは64ビットシステムにポインタを与えることを選択しました8 bytes
、構造体のintは4 bytes
を持っています。昔は同じような問題や警告が以前のコード例で作業していることが多いので、もっと深く掘り下げる必要がありました。
簡潔にするために、int
は60年代に定義され、64ビットシステム、ギガバイトのストレージもGBのRAMも考慮されていませんでした。
エラーメッセージを解決するには、必要に応じてint
ではなくsize_t
(size type)を使用します。map stlを使用する場合は、複数の異なるシステムで実行するようにプログラムされています。
size_t
を使用すると、32ビットシステムまたは64ビットシステムまたはアームでコンパイルする場合、コンパイラーは必要なバイトサイズを自分で選択できます。メッセージが表示されなくなり、コードを変更する必要もありません。将来コードをコンパイルするシステムに関係なく。