C++——内存管理

内存管理

1.类的对象存储空间

一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。

成员函数不占用对象的内存

一个类所占空间由以下几点决定:

  • 非静态成员的数据类型大小之和。
  • 编译器加入的额外成员变量(如指向虚函数表的指针)。
  • 为了边缘对齐优化加入的padding
class A {}; // 1
class A { virtual void Fun(){} }; // 4
class A { static int a; }; // 1
class A { int a; }; // 4
class A { static int a; int b; }; // 4

2.C++的内存分区

在这里插入图片描述

:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限

:就是那些由 new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个 delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收

自由存储区:如果说堆是操作系统维护的一块内存,那么自由存储区就是C++中通过new和delete动态分配和释放对象的抽象概念。需要注意的是,自由存储区和堆比较像,但不等价。

全局/静态存储区全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量和静态变量又分为初始化的和未初始化的,在C++里面没有这个区分了,它们共同占用同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如int型变量自动初始为0

常量存储区:这是一块比较特殊的存储区,这里面存放的是常量,不允许修改

代码区:存放函数体的二进制代码,所有函数都放在这,包括静态函数

3.内存池如何实现

C++内存池是一种用于管理和分配内存的技术。它通过预先分配一块连续的内存空间,并按照一定的策略将其分割为多个小块,然后根据需要分配这些小块的内存。

allocate 包装 malloc,deallocate包装free

  1. 首先客户端会调用malloc()配置一定数量的区块(固定大小的内存块,通常为8的倍数),假设40个32bytes的区块,其中20个区块(一半)给程序实际使用,1个区块交出,另外19个处于维护状态。剩余20个(一半)留给内存池,此时一共有(20*32byte)。先用一半,留着一半

  2. 客户端之后有有内存需求,想申请(20*64bytes)的空间,这时内存池只有(20*32bytes),就先将(10*64bytes)个区块返回,1个区块交出,另外9个处于维护状态,此时内存池空空如也.

  3. 接下来如果客户端还有内存需求,就必须再调用malloc()配置空间,此时新申请的区块数量会增加一个随着配置次数越来越大的附加量,同样一半提供程序使用,另一半留给内存池。申请内存的时候用永远是先看内存池有无剩余,有的话就用上,然后挂在0-15号某一条链表上,要不然就重新申请。

  4. 如果整个堆的空间都不够了,就会在原先已经分配区块中寻找能满足当前需求的区块数量,能满足就返回,不能满足就向客户端报bad_alloc异常

4.this指针

  • this指针是的指针,指向对象的首地址。不会影响对象的大小

  • this指针只能在成员函数中使用,在全局函数、静态成员函数中都不能用this。

  • this指针只有在成员函数中才有定义,且存储位置会因编译器不同有不同存储位置。

A a;
a.func(10);//此处,编译器将会编译成:A::func(&a,10);
  1. this指针是什么时候创建的?

    this在成员函数的开始执行前构造,在成员函数的执行结束后清除。

  2. this指针存放在何处?

    this指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。

  3. this指针是如何传递到类中的函数?

    this指针在调用之前生成,然后通过函数参数的首参来传递的

  4. this指针是如何访问类中的变量的?

    类似于结构体的指针,this是类的指针,如果换成结构体,那this就是结构的指针了。

  5. 如果我们知道一个对象this指针的位置,可以直接使用吗?

    this指针只有在成员函数中才有定义。而且标准情况下this为右值,即使在成员函数里,也无法通过&符号获取地址,

  6. 每个类编译后,是否创建一个类中函数表保存函数指针,以便用来调用函数?

    普通的类函数都不会创建一个函数表来保存函数指针。只有虚函数才会被放到函数表中。

5.内存泄漏的后果?如何监测?解决方法?

内存泄漏是指由于疏忽或错误造成了程序未能释放掉不再使用的内存的情况。内存泄漏并非指内存在物理上消失,而是应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制

BoundsChecker是一个运行时错误检测工具,它主要定位程序运行时期发生的各种错误;

使用智能指针避免内存泄露。

6.空类的大小

  1. C++中要求对于类的每个实例都必须有独一无二的地址,那么编译器自动为空类分配一个字节大小,这样便保证了每个实例均有独一无二的内存地址。

  2. 带有虚函数的C++空类大小不为1,因为每一个对象会有一个vptr指向虚函数表,具体大小根据指针大小确定;

7.this指针调用成员变量时,堆栈会发生什么变化

当在类的非静态成员函数访问类的非静态成员时,编译器会自动将对象的地址传给作为隐含参数传递给函数,这个隐含参数就是this指针,对各成员的访问都是通过this的。this指针首先入栈,然后成员函数的参数从右向左进行入栈,最后函数返回地址入栈。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值