C++ sizeof的各种

发布于:2024-06-29 ⋅ 阅读:(16) ⋅ 点赞:(0)

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;
}


网站公告

今日签到

点亮在社区的每一天
去签到