C++对象内存布局(1)

本文探讨了C++中对象的内存布局,包括基础类型的内存占用、类的填充原则、栈与堆内存分配的差异、Debug和Release模式下的内存表现,以及New和Delete操作在数组对象上的使用细节。强调了理解内存布局对于避免内存泄漏和优化性能的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基础类型

基础类型
注意:在有的机器上double是4bytes。

类的填充问题

class A {
    int a;
    short b;
    int c;
    char d;
};
class B {
    double a;
    int c;
    double d;
    int e;
};

类的size计算的基本原则是:
1. 类的单位是以块(Block)计算的,一块等于类中最大成员的size
2. 类的大小是块的整数倍,比如A最大的成员是Int,所以A的size为4的倍数,而B为8的倍数(在这里double为8个byte)
3. 类的对象模型是按声明顺序排序的,也就是一个对象挨着一个对象排序,如果对象相加不到一块的大小,则填充这个类,使其达到块的大小

A和B的大小分别为16和32。

栈和堆以及内存分配

我们分配内存有两种方式,一种是分配在栈上,一种是分配到堆上。

我们在一个作用域上分配的临时变量就是分配在栈上,离开作用域就会自动销毁,常见的场景有传入参数和声明初始化用于循环时的index变量。

典型的栈变量:

int i = 0;
Complex s1(1, 2);
Complex s2(3, 4);

栈对象由系统自动回收,所以我们无需手动删除对象。

而堆对象则需要我们手动删除对象并回收内存,堆对象主要是用molloc和new分配的内存。

Complex* p_s = new Complex(5, 5);
delete p_s;

堆对象给了我们很大的灵活性,但同时也带来了危险。

自由的代价就是永远的警惕!

如果我们分配在堆上分配了内存,但却没有回收,则会造成内存泄漏,短时间运行的程序可能没什么,毕竟程序关闭则所有内存都会回收,但如果是长时间运行的程序则会造成严重的内存浪费问题,影响运行性能。

可以光有堆而没有栈吗?或者反过来呢?

在这里就明确告诉你——不兹慈!

为什么呢?因为栈对象是编译时就已经确定了大小,在运行时就无法分配更多内存了,如果全部是栈对象,那么当我们需要更多内存时就悲剧了。

如果只有堆的话更不行,因为指针是在栈上分配的,可是你连可以分配堆对象的指针对象都没有,怎么分配内存?

Debug和Release模式

在Debug模式下,一个类实际会增加很多调试信息,所以实际在内存中的size远远不止你用sizeof看到的这点。在Release对象中也是会夹杂一点内存的信息,否则系统就不知道从哪里开始回收内存了。

而数组对象和普通对象在内存中的存储方式也不一样,数组对象他会在实际的对象前保存这个数组的长度。而普通对象则不会这么做。

New和Delete以及Array

在用指针在堆上创建对象时,一般使用new关键字创建用delete关键字删除。而我们在创建数组时,却必须要使用delete[] 关键字。这是为什么呢?下面我们就来看一下它们内部的实现原理。

delete关键字回收对象的内存模型,也就是说长条的长方形中所有内存都会被释放,如果该对象是指针,则释放第一个指针对象。

好了,现在你应该知道为什么数组应该使用delete[]关键字了吧。如果数组不是指针数组那么这两个关键字都可以释放内存,但如果数组是指针数组,那么指针所指向的堆的内存则不会被释放,从而造成大量的内存泄漏!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值