具有4个字节的"填充类'测试器'警告意味着什么?

Dun*_*eal 30 c++ compiler-warnings clang++

对于这个简化的测试用例:

#include <map>

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

int main() {
    Tester test; 
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到以下编译器警告:

$ 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;
                       ^
Run Code Online (Sandbox Code Playgroud)

任何人都可以解释这个警告意味着什么,以及我应该如何解决它?

Tri*_*dle 25

这里没有真正的问题.在C和C++中,允许编译器在struct成员之后插入填充以提供更好的对齐,从而允许更快的内存访问.在这种情况下,它似乎决定smap放在8字节对齐上.由于int几乎肯定是四个字节,警告告诉您结构中间有四个字节的浪费空间.

如果结构中有更多成员,那么您可以尝试的一件事就是切换定义的顺序.例如,如果您Tester有成员:

 struct Tester {
     int foo;
     std::map<int, int> smap;
     int bar;
 };
Run Code Online (Sandbox Code Playgroud)

那么将两个整体放在一起以优化对齐并避免浪费空间是有意义的.但是,在这种情况下,您只有两个成员,如果您切换它们,那么编译器可能仍然会在结构的末尾添加四个字节的填充,以便Tester在放入数组时优化s 的对齐.

  • 您可以在代码中忽略它,例如:`#pragma clang diagnostic push` `#pragma clang 诊断忽略“-Wpadded”` `volatile bool connected = true;` `#pragma clang diagnostic pop` (2认同)

Jon*_*art 5

我假设你在64位系统上编译它.

在64位系统上,指针是8个字节.编译器会将结构成员与自然边界对齐,因此8字节指针将从结构中的偏移量开始,该结构是8字节的倍数.

由于int只有四个字节,编译器在之后插入了4个字节的"填充" foo,因此它smap位于一个8字节的边界上.

编辑:虽然smap不是指针,但是a std::map,同样的逻辑适用.我不确定对象对齐的确切规则是什么,但同样的事情正在发生.

该怎么办?没有.你的代码非常好,编译器只是让你知道这已经发生了.绝对没有什么可担心的. -Weverything意味着打开每一个可能的警告,这对于大多数编辑来说可能都是过多的.

  • @DunPeal它不只是内存将被_wasted_,它也是,如果你的二进制序列化这种数据结构,然后反序列化它,说一个32位的机器上,你将拥有这片神秘的填充在那里,你可能不知道插入的编译器.虽然你不会二进制序列化`std :: map`,但仍然如此.如果这是一些可以将自己借给简单二进制序列化的原语,那么你可能已经完成了它.编译器希望你知道`smap`将比你想象的更早4个字节. (3认同)