C++ sizeof的各种
- 1. 含有虚函数的类对象的空间大小
- 2. 虚拟继承的类对象的空间大小
- 3. 普通变量所占空间大小
- 4. 复合数据类型(结构体和类)
- 5. 数组
- 6. 类型别名
- 7. 动态分配内存
- 8. 指针
- 9. 静态变量
- 10. 联合体
- 11. 结构体使用#program pack
1. 含有虚函数的类对象的空间大小
在C++中,含有虚函数的类对象的大小不仅包括其成员变量的大小,还包括一个指向虚函数表(vtable)的指针的大小。这个指针用于动态绑定函数调用。在32位系统中,这个指针通常是4字节,在64位系统中则是8字节。
#include <iostream>
class Base {
public:
virtual void func() {} //32:4字节,64:8字节
};
class Derived : public Base {
int a; //4
double b; //8
};
int main() {
std::cout << "Size of Base: " << sizeof(Base) << std::endl; // 8
std::cout << "Size of Derived: " << sizeof(Derived) << std::endl; //8+4+8
return 0;
}
结果(64位系统)
Size of Base: 8
Size of Derived: 24
2. 虚拟继承的类对象的空间大小
在C++中,虚拟继承用于解决多重继承中的菱形继承问题。虚拟继承会影响类对象的内存布局,因为编译器需要在运行时解决虚基类的共享问题,这通常通过引入指针或指针表来实现。
#include <iostream>
class A{
};
class Base {
public:
int baseData;
};
class Derived1 : virtual public Base {
public:
int derived1Data;
};
class Derived2 : virtual public Base {
public:
int derived2Data;
};
class Final : public Derived1, public Derived2 {
public:
int finalData;
};
int main() {
std::cout << "Size of A: " << sizeof(A) << std::endl; // 1
std::cout << "Size of Base: " << sizeof(Base) << std::endl; // 4
std::cout << "Size of Derived1: " << sizeof(Derived1) << std::endl; // 4 + 8 + 4 = 16
std::cout << "Size of Derived2: " << sizeof(Derived2) << std::endl; // 4 + 8 + 4 = 16
std::cout << "Size of Final: " << sizeof(Final) << std::endl; // 8 + 8 + 4 + 4 + 4 + 4 = 32
return 0;
}
结果
Size of Base: 4
Size of Derived1: 16
Size of Derived2: 16
Size of Final: 32
对Final类详细解释:
虚基类Base的成员只存在一份,但需要存储指针或指针表以便在运行时正确访问。
8 bytes (虚基类指针 1) +
8 bytes (虚基类指针 2) +
4 bytes (Derived1::derived1Data) +
4 bytes (Derived2::derived2Data) +
4 bytes (Final::finalData) +
4 bytes (Base::baseData)
= 32 bytes
3. 普通变量所占空间大小
在C++中,使用sizeof运算符可以计算普通变量所占用的内存空间大小。不同类型的变量占用的内存空间大小可能因系统架构(如32位和64位)和编译器的不同而有所差异。
以下是一些常见的数据类型及其在不同系统上的典型大小:
解释对long的sizeof:
在64位系统上,long 类型的大小实际上取决于编译器和操作系统的实现。有些系统(特别是遵循 LP64 数据模型的类 Unix 系统)将 long 定义为 8 个字节,而其他系统(如 Windows)可能会将 long 定义为 4 个字节。
#include <iostream>
int main() {
std::cout << "Size of char: " << sizeof(char) << " bytes" << std::endl;
std::cout << "Size of bool: " << sizeof(bool) << " bytes" << std::endl;
std::cout << "Size of short: " << sizeof(short) << " bytes" << std::endl;
std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl;
std::cout << "Size of float: " << sizeof(float) << " bytes" << std::endl;
std::cout << "Size of double: " << sizeof(double) << " bytes" << std::endl;
std::cout << "Size of long: " << sizeof(long) << " bytes" << std::endl;
std::cout << "Size of long long: " << sizeof(long long) << " bytes" << std::endl;
std::cout << "Size of void*: " << sizeof(void*) << " bytes" << std::endl;
return 0;
}
结果
Size of char: 1 bytes
Size of bool: 1 bytes
Size of short: 2 bytes
Size of int: 4 bytes
Size of float: 4 bytes
Size of double: 8 bytes
Size of long: 8 bytes // 在64位系统上
Size of long long: 8 bytes
Size of void*: 8 bytes // 在64位系统上
4. 复合数据类型(结构体和类)
#include <iostream>
struct MyStruct {
int a; // 4
double b; // 8
char c; // 1 -> 4
};
class MyClass {
public:
int x; // 4
float y; // 4
char z; // 1 -> 4
};
int main() {
std::cout << "Size of MyStruct: " << sizeof(MyStruct) << " bytes" << std::endl; // 对齐后16
std::cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << std::endl; // 对齐后 12
return 0;
}
5. 数组
#include <iostream>
int main() {
int arr[10];
std::cout << "Size of int array[10]: " << sizeof(arr) << " bytes" << std::endl; // 4 * 10 = 40
return 0;
}
6. 类型别名
#include <iostream>
typedef int MyInt;
typedef double MyDouble;
int main() {
std::cout << "Size of MyInt: " << sizeof(MyInt) << " bytes" << std::endl; // 4
std::cout << "Size of MyDouble: " << sizeof(MyDouble) << " bytes" << std::endl; // 8
return 0;
}
7. 动态分配内存
#include <iostream>
int main() {
int* ptr = new int[10];
std::cout << "Size of pointer to int[10]: " << sizeof(ptr) << " bytes" << std::endl; // 8
std::cout << "Size of dynamically allocated int[10]: " << sizeof(*ptr) * 10 << " bytes" << std::endl; // 4 * 10 = 40
delete[] ptr;
return 0;
}
8. 指针
在一个64位系统上,所有指针的大小通常是8字节
#include <iostream>
int main() {
int* intPtr;
double* doublePtr;
char* charPtr;
std::cout << "Size of char pointer: " << sizeof(charPtr) << " bytes" << std::endl; // 8
std::cout << "Size of int pointer: " << sizeof(intPtr) << " bytes" << std::endl; // 8
std::cout << "Size of double pointer: " << sizeof(doublePtr) << " bytes" << std::endl; // 8
return 0;
}
9. 静态变量
静态变量的大小可以用sizeof运算符计算,但它们不计入包含它们的类的实例的大小。
#include <iostream>
class MyClassWithStatic {
public:
static int staticVar;
int regularVar;
};
int MyClassWithStatic::staticVar = 0;
int main() {
std::cout << "Size of MyClassWithStatic: " << sizeof(MyClassWithStatic) << " bytes" << std::endl; // 4
std::cout << "Size of MyClassWithStatic::staticVar: " << sizeof(MyClassWithStatic::staticVar) << " bytes" << std::endl; // 4
return 0;
}
10. 联合体
MyComplexUnion 的最大成员是 double,大小为 8 字节
#include <iostream>
struct MyStruct {
int x;
char y;
};
union MyComplexUnion {
int a;
double b;
MyStruct c;
};
int main() {
std::cout << "Size of MyComplexUnion: " << sizeof(MyComplexUnion) << " bytes" << std::endl; // 8
std::cout << "Size of int: " << sizeof(int) << " bytes" << std::endl;
std::cout << "Size of double: " << sizeof(double) << " bytes" << std::endl;
std::cout << "Size of MyStruct: " << sizeof(MyStruct) << " bytes" << std::endl;
return 0;
}
11. 结构体使用#program pack
在C++中,结构体的大小不仅取决于其成员的大小,还取决于成员的排列方式和编译器对齐策略。通常情况下,编译器会为结构体的成员添加填充字节,以确保成员在内存中的地址满足对齐要求。
我们可以使用预处理指令#pragma pack来改变编译器的对齐策略,从而影响结构体的大小。比如:#program pack(2),就是按2对齐。
#include <iostream>
struct MyStruct {
char a; // 1
int b; // 4
short c; // 2
}; // 4 + 4 = 8
#pragma pack(1)
struct MyPackedStruct {
char a; // 1
int b; // 4
short c; // 2
}; // 7
#pragma pack()
#pragma pack(2)
struct MyPackedStruct2 {
char a; // 1->2
int b; // 4
short c; // 2
}; // 2 + 4 + 2 = 8
#pragma pack()
#pragma pack(4)
struct MyPackedStruct4 {
char a; // 1 -> 4
int b; // 4
short c; // 2 -> 4
}; // 12
#pragma pack()
int main() {
std::cout << "Size of MyStruct: " << sizeof(MyStruct) << " bytes" << std::endl; // 8
std::cout << "Size of MyPackedStruct: " << sizeof(MyPackedStruct) << " bytes" << std::endl; // 7
std::cout << "Size of MyPackedStruct2: " << sizeof(MyPackedStruct2) << " bytes" << std::endl; // 8
std::cout << "Size of MyPackedStruct4: " << sizeof(MyPackedStruct4) << " bytes" << std::endl; // 12
return 0;
}