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

时间:2013-11-25 03:28:23

标签: c++ compiler-warnings clang++

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

#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;
                       ^

任何人都可以解释这个警告意味着什么,以及我该如何处理它?<​​/ p>

3 个答案:

答案 0 :(得分:21)

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

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

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

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

答案 1 :(得分:5)

我假设您正在64位系统上进行编译。

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

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

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

怎么办?没有。你的代码非常好,编译器只是让你知道这已经发生了。绝对没有什么可担心的。 -Weverything表示启用every possible warning,这对于大多数编辑来说可能都是过量的。

答案 2 :(得分:0)

您的sytsem上的编译器选择在64位系统8 bytes上提供指针,该结构中的int具有4 bytes。那些日子里,使用较旧的代码示例时,我经常遇到类似的问题/警告,所以我不得不更深入地研究。

简而言之,int是在60年代定义的,没有64位系统,没有千兆字节的存储空间,也没有GB的内存。

要解决错误消息,请在必要时使用size_t (大小类型)代替int-在您的情况下,请使用 map stl 它被编程为可以在多个不同的系统上运行。

如果使用size_t,则编译器可以自行选择在32位系统或64位系统或arm上进行编译时所需的字节大小,或者消息消失了,而您甚至不必无论您将来使用哪种系统编译代码,都可以修改代码。