如何确定C ++类的大小? [英] How is the size of a C++ class determined?

查看:128
本文介绍了如何确定C ++类的大小?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

摘要:编译器如何在编译期间静态确定C ++类的大小?

Summary: How does the compiler statically determine the size of a C++ class during compilation?

Details:

我试图理解一个规则是用来确定一个类将使用多少内存,以及如何对齐内存。

I'm trying to understand what the rules are for determining how much memory a class will use, and also how the memory will be aligned.

例如下面的代码声明了4个类。前2个都是16字节。但是3是48字节,尽管它包含与第一个2相同的数据成员。虽然第四个类有与第三个相同的数据成员,只是在不同的顺序,但它是32字节。

For example the following code declares 4 classes. The first 2 are each 16 bytes. But the 3 is 48 bytes, even though it contains the same data members as the first 2. While the fourth class has the same data members as the third, just in a different order, but it is 32 bytes.

#include <xmmintrin.h>
#include <stdio.h>

class TestClass1 {
  __m128i vect;
};

class TestClass2 {
  char buf[8];
  char buf2[8];
};

class TestClass3 {
  char buf[8];
  __m128i vect;
  char buf2[8];
};

class TestClass4 {
  char buf[8];
  char buf2[8];
  __m128i vect;
};


TestClass1 *ptr1;
TestClass2 *ptr2;
TestClass3 *ptr3;
TestClass4 *ptr4;
int main() {
  ptr1 = new TestClass1();
  ptr2 = new TestClass2();
  ptr3 = new TestClass3();
  ptr4 = new TestClass4();
  printf("sizeof TestClass1 is: %lu\t TestClass2 is: %lu\t TestClass3 is: %lu\t TestClass4 is: %lu\n", sizeof(*ptr1), sizeof(*ptr2), sizeof(*ptr3), sizeof(*ptr4));
  return 0;
}



我知道答案与数据成员的对齐有关班上。但我想弄清楚这些规则是什么以及它们如何在编译步骤中应用,因为我有一个类有一个 __ m128i 数据成员,但数据成员是不是16字节对齐,当编译器使用 movaps 生成代码以访问数据时,会导致segfault。

I know that the answer has something to do with alignment of the data members of the class. But I am trying to understand exactly what these rules are and how they get applied during the compilation steps because I have a class that has a __m128i data member, but the data member is not 16-byte aligned and this results in a segfault when the compiler generates code using movaps to access the data.

推荐答案

对于POD(普通旧数据),规则通常是:

For POD (plain old data), the rules are typically:


  • 结构具有一些大小s和一些对齐要求a。

  • 编译器开始时大小S设置为零,对齐要求A设置为一(字节)。

  • 编译器按顺序处理结构中的每个成员:
  • Each member in the structure has some size s and some alignment requirement a.
  • The compiler starts with a size S set to zero and an alignment requirement A set to one (byte).
  • The compiler processes each member in the structure in order:

  1. 考虑成员的对齐要求a。如果S当前不是a的倍数,那么只需要添加足够的字节S,使得它是a的倍数。这决定了成员将去哪里;它将从结构的开始(对于S的当前值)偏移S处。

  2. 将A设置为A和a的最小公倍数。

  3. 将S添加到S,为成员预留空间。


  • ,考虑结构的对齐要求A.如果S当前不是A的倍数,那么只需将S足够加到S的倍数上,以便它是A的倍数。

  • 当上述操作完成后,结构的大小是S的值。

    The size of the structure is the value of S when the above is done.

    此外:


    • 如果任何成员是数组,其大小是元素数乘以每个元素的大小,其对齐要求是元素的对齐要求。

    • 如果任何成员是结构,则其大小和对齐要求按上述计算。

    • 如果任何成员是联合:
    • If any member is an array, its size is the number of elements multiplied by the size of each element, and its alignment requirement is the alignment requirement of an element.
    • If any member is a structure, its size and alignment requirement are calculated as above.
    • If any member is a union:

    1. 将S设置为最大成员的大小。

    2. 将A设置为所有成员对齐的最小公倍数。

    3. 如果S不是A的倍数,只需将S加到S的倍数,使其成为A的倍数。


    考虑您的 TestClass3


    • <0> A从$ 1开始。

    • char buf [8] 需要8个字节和对齐方式1,所以S增加8到8,并且A保持为1.

    • __ m128i vect 需要16个字节和对齐16.首先,S必须增加到16给出正确的对齐方式。然后A必须增加到16.那么S必须增加16才能为 vect 增加空间,因此S现在为32.

    • char buf2 [8] 需要8个字节和对齐方式1,所以S增加8到24,A保持为16。

    • 最后,S是24,它不是A(16)的倍数,因此S必须增加8到32。

    • S starts at 0 and A starts at 1.
    • char buf[8] requires 8 bytes and alignment 1, so S is increased by 8 to 8, and A remains 1.
    • __m128i vect requires 16 bytes and alignment 16. First, S must be increased to 16 to give the right alignment. Then A must be increased to 16. Then S must be increased by 16 to make space for vect, so S is now 32.
    • char buf2[8] requires 8 bytes and alignment 1, so S is increased by 8 to 24, and A remains 16.
    • At the end, S is 24, which is not a multiple of A (16), so S must be increased by 8 to 32.

    因此 TestClass3 的大小为32个字节。

    So the size of TestClass3 is 32 bytes.

    对于基本类型( int double 等),对齐要求是依赖于实现的,并且在很大程度上由硬件确定。在许多处理器上,加载和存储数据时具有特定对齐方式(通常是在存储器中的地址是其大小的倍数时)更快。除此之外,上述规则大部分遵循逻辑;他们将每个成员放在必须满足对齐要求的位置,而不使用比必要的更多空间。

    For elementary types (int, double, et cetera), the alignment requirements are implementation dependent and are largely determined by the hardware. On many processors, it is faster to load and store data when it has a certain alignment (usually when its address in memory is a multiple of its size). Beyond this, the rules above follow largely from logic; they put each member where it must be to satisfy alignment requirements without using more space than necessary.

    这篇关于如何确定C ++类的大小?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆