对于这个简化的测试用例:
#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>
答案 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上进行编译时所需的字节大小,或者消息消失了,而您甚至不必无论您将来使用哪种系统编译代码,都可以修改代码。