类的对象的二进制体系结构中的成员的顺序是否会对使用该类的应用程序的性能产生影响?我想知道如果答案是肯定的,如何决定POD成员的顺序,因为程序员通过他们的声明顺序来定义成员的顺序
答案 0 :(得分:28)
绝对。 C ++保证内存中对象的顺序与声明顺序相同,除非访问限定符介入。
直接相邻的对象更可能位于同一个高速缓存行上,因此一次内存访问将同时获取它们(或从缓存中刷新两者)。缓存有效性也可以得到改善,因为其中的有用数据的比例可能更高。简而言之,代码中的空间局部性转换为性能的空间局部性。
另外,正如Jerry在评论中指出的那样,订单可能会影响填充量。通过减小大小来对成员进行排序,这也是通过减少对齐(通常将数组视为其类型的一个元素,将成员结构视为其最对齐的成员)。不必要的填充可能会增加结构的总大小,从而导致更高的内存流量。
C ++03§9/ 12:
a的非静态数据成员 (非联合)类声明没有 中间访问说明符被分配,以便后来的成员具有 一个班级中较高的地址 宾语。分配顺序 由...分隔的非静态数据成员 access-specifier未指定 (11.1)。实施一致 要求可能会导致两个 相邻成员不得分配 紧接着彼此;可能 管理空间要求 虚函数(10.3)和虚函数 基类(10.1)。
答案 1 :(得分:7)
绝对同意Potatoswatter。但是,还应该添加一个关于CPU缓存行的要点。
如果您的应用程序是多线程的,并且不同的线程读/写您的结构成员 - 确保这些成员在同一个缓存行中不非常重要。
关键是每当线程修改在其他CPU中缓存的内存地址时 - 该CPU立即使包含该地址的缓存行无效。因此,不正当的成员订单可能会导致不合理的缓存失效和性能下降。
答案 2 :(得分:4)
除了运行时性能,在缓存行相关的答案中描述,我认为还应该考虑内存性能,即类对象的大小。
由于padding,类对象的大小取决于成员变量声明的顺序。
以下声明可能需要12个字节
class foo {
char c1;
int i;
char c2;
}
但是,在对成员声明的顺序进行简单的重新排序时,以下内容可能需要8个字节
class bar {
int i;
char c1;
char c2;
}
在与4字节字对齐的机器中:
sizeof( foo ) = 12
但
sizeof( bar ) = 8