C++内存大小计算总结

总结

类(C++的struct等价class)的内存大小占用问题(三个部分)

  1. 非静态(non-static)数据成员大小;(成员函数不占内存,想想如果占内存的话,我多加些 那不内存爆炸了~
  2. 虚函数表指针(若存在virtual function,则+8(vptr指针的sizeof均是8)
  3. 内存对齐填充的padding

空类的 sizeof 为1.

内存对齐原则

参考:https://blog.csdn.net/luolaihua2018/article/details/115372273

  1. 数据成员对齐规则,结构体(struct)(或联合(union))的数据成员,第一个数据成员存放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员(只要该成员有子成员,比如数组、结构体等)大小的整数倍开始(如:int 在 64bit 目标平台下占用 4Byte,则要从4的整数倍地址开始存储);
  2. 结构体作为成员,如果一个结构体里有某些结构体成员,则结构体成员要从内部最大元素大小的整数倍地址开始存储
  3. 结构体的总大小,即sizeof的结果,必须是其内部最大成员长度(即前面内存对齐指令中提到的有效值)的整数倍,不足的要补齐

union内存大小

union结构大小是最大成员所占大小+(为了符合内存对齐原则填充的padding)

enum大小

参考:https://blog.csdn.net/chenjiayi_yun/article/details/15832425

C++中枚举变量的大小是 1<=sizeof(enum)<=sizeof(int) 字节 (1-4字节)

枚举默认是用int类型来存储的,占4个字节。可以存储的最大值是0xffffff。可以通过继承方式改变枚举的大小

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class AA {
    public:
    enum EnumTest
    {a =1,b = 5};//枚举类型没有占用内存(占用内存的只是变量)
};

// 枚举默认是用int类型来存储的,占4个字节。可以存储的最大值是0xffffff。
// 可以通过继承方式改变枚举的大小
// C++中枚举变量的大小是 1<=sizeof(enum)<=sizeof(int) 字节 (1-4字节)
enum EnumTest {
    a =1,b = 5  // 默认是int类型
};

class BB {
    enum EnumTest enumTest1;
};

enum EnumChar : unsigned char {
    A = 0x00,
    B,
    C = 0xff
};

// size of enum 4
// Class AA veriable size 1
// Class BB veriable size 4
// sizeof EnumChar 1
int main() {
    cout << "size of enum "<< sizeof(EnumTest) << endl;         // 4
    cout << "Class AA veriable size " << sizeof(AA) << endl;    //内存大小最少是1字节(所以class A这里是1字节)
    cout << "Class BB veriable size " << sizeof(BB) << endl;    // 4
    cout << "sizeof EnumChar "<< sizeof(EnumChar) << endl;      // 1
    return 0;
}

全部测试代码

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*** 
 * @Date: 2022-03-07 13:55:22
 * @Author: yufeng
 * @GitHub: https://github.com/fzhiy
 * @Email: fzhiy270@163.com
 * @LastEditTime: 2022-03-10 10:42:07
 */
#include <bits/stdc++.h>
using namespace std;

class A {
    int a;
public: 
    A() { cout << "A()" << endl; }
    ~A() {cout << "~A()" << endl; }
    void print() {
        cout << "this is class A.print()" << endl;
    }
};

class B {
    int b;
public: 
    B() { cout << "B()" << endl; }
    ~B() {cout << "~B()" << endl; }
    virtual void print() {
        cout << "this is class B.print()" << endl;
    }
};

class C : public B {
    int c;
public: 
    C() { cout << "C()" << endl; }
    ~C() {cout << "~C()" << endl; }
    virtual void print() override { 
        // oerride关键字 确保此函数 覆盖了父类B的print()函数, 确保不会出现函数名打错的情况
        cout << "this is class C.print()" << endl;
    }
};

class D : public C {
    int d;
    int dc = 5;
    // const static int da = 5;     // 允许
    // const int dab = 5;           // 允许
    // static int dac = 5;          // 不允许, static变量必须在类外面初始化, 因为static变量属于整个类, 而不属于某个对象
public: 
    D() { cout << "D()" << endl; }
    ~D() {cout << "~D()" << endl; }
    void print() final {
        // final关键字 确保print()函数不会被其子类(如果有子类的话)覆盖(override)
        cout << "this is class D.print()" << endl;
    }
};

class E {
};

/** 类的内存空间大小占用计算(三个部分):
 *  1) 非静态(non-static)数据成员大小
 *  2) 虚函数表指针(若存在virtual function, 则 +8 (vptr指针的sizeof均是8))
 *  3) 内存对齐填充的padding
 */ 
// class F {
//     virtual void Func() {;}
// };
// int main() {
//     cout << sizeof(F) << endl;  // 8
//     E e;
//     cout << sizeof(E) << endl;  // 1    C++中 空类的大小为1
//     cout << sizeof(e) << endl;  // 1    保证 类的每个实例 独一无二
//     A a;
//     a.print();
//     cout << sizeof(A) << endl;  // 4
//     cout << sizeof(a) << endl;  // 4
//     B b;
//     b.print();
//     cout << sizeof(b) << endl;  // 16
//     cout << sizeof(b) << endl;  // 16   (4 + 8 + 4(内存对齐)一个虚函数表的指针大小 占用  bytes)
//     C c;
//     c.print();
//     cout << sizeof(C) << endl;  // 16
//     cout << sizeof(c) << endl;  // 16   (4 + 8 + 4(class C中的非静态数据成员c的大小))
//     D d;
//     d.print();
//     cout << sizeof(D) << endl;  // 24
//     cout << sizeof(d) << endl;  // 24, (4 + 8 + 4 + 4 + 4(内存对齐))如果 C 的成员函数print()加了virtual 输出会是 24

//     return 0;
// }

// enum Day {
//     one = '1',
//     two = '2',
//     three = '3',
//     four = '4',
//     five = '5'
// };

// int main() {
//     int a = 4;
//     char *str[] = {"asbih", "adjao", "haode"};
//     char** p = str;
//     Day d;
//     cout << sizeof(d) << endl;      //4
//     cout << sizeof(str[0]) << endl; //8 str[i] 都是一个指针
//     cout << sizeof(p) << endl;      //8 p是一个 指向指针的指针
//     cout << sizeof(&a) << endl;     //8
//     cout << sizeof(a) << endl;      // 4
//     cout << sizeof(int) << endl;    // 4
//     cout << sizeof(int*) << endl;   // 8
//     cout << sizeof(float) << endl;      //4 
//     cout << sizeof(float*) << endl;     //8 凡是指针类型,其sizeof都是8 bytes
//     cout << sizeof(double) << endl;     //8 
//     cout << sizeof(long) << endl;       //4 
//     cout << sizeof(long long) << endl;  //8
//     cout << sizeof(unsigned long long) << endl; //8
// }

// 兴业数金
typedef union tagPeople {
    int age;
    char name[5];
    char sex;
}People_t, *People_tp;

typedef union UnionStruct {
};
union UnionStruct2 {
    char a[5];
    int age;
    float c;
    // double d;
    // string s;
};

union Test{
    char a[20];
    int b;
    float c;
};

union Test2{
    char a[20];
    int b;
    float c;
    double d;
};
struct TestStruct{
    char a[20];
    int b;
    float c;
};
struct TestStruct2{
    char a[20];
    int b;
    float c;
    double d;   // 结构体内最大元素的大小 8
    void fun() { cout << "TestStruct2" << endl; }
};

int main() {
    cout << sizeof(TestStruct) << endl;     // 28 = 20 + 4 + 4
    cout << sizeof(TestStruct2) << endl;    // 40 = 20 + 4 + 4 + 8 + 4(内存对齐)
    cout << sizeof(Test) << endl;   // 20
    cout << sizeof(Test2) << endl;  // 24 = 20 + 4(内存对齐,24是最大成员double类型d的 3倍)
    char a[5];
    char *p = a;    // 虽然数组名a也是数组a的首地址,指针p指向了它。但是sizeof(a) = 数组的实际大小
    // cout << sizeof(p) << endl;              // 8
    cout << sizeof(a) << endl;              // 5  = 5 * 1
    int b[5];
    int *ip = b;
    cout << sizeof(b) << endl;              // 20 = 5 * 4
    // cout << sizeof(ip) << endl;             // 8
    cout << sizeof(UnionStruct) << endl;    // 1
    cout << sizeof(string) << endl;         // 32
    cout << sizeof(UnionStruct2) << endl;   // 8 (找Union中最大的数据类型,还必须满足是所有成员的整数倍)
    cout << sizeof(int) << endl;            // 4
    cout << sizeof(People_t) << endl;       // 8
    cout << sizeof(People_tp) << endl;      // 8 (64位操作系统中指针大小为8,32位)   
    return 0;
}

// class AA {
//     public:
//     enum EnumTest
//     {a =1,b = 5};//枚举类型没有占用内存(占用内存的只是变量)
// };

// // 枚举默认是用int类型来存储的,占4个字节。可以存储的最大值是0xffffff。
// // 可以通过继承方式改变枚举的大小
// // C++中枚举变量的大小是 1<=sizeof(enum)<=sizeof(int) 字节 (1-4字节)
// enum EnumTest {
//     a =1,b = 5  // 默认是int类型
// };

// class BB {
//     enum EnumTest enumTest1;
// };

// enum EnumChar : unsigned char {
//     A = 0x00,
//     B,
//     C = 0xff
// };

// // size of enum 4
// // Class AA veriable size 1
// // Class BB veriable size 4
// // sizeof EnumChar1
// int main() {
//     cout << "size of enum "<< sizeof(EnumTest) << endl;         // 4
//     cout << "Class AA veriable size " << sizeof(AA) << endl;    //内存大小最少是1字节(所以class A这里是1字节)
//     cout << "Class BB veriable size " << sizeof(BB) << endl;    // 4
//     cout << "sizeof EnumChar "<< sizeof(EnumChar) << endl;      // 1
//     return 0;
// }