2021-10-21面向对象:动态分配所得的内存块笔记
Posted 阿宝逃离地球
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-10-21面向对象:动态分配所得的内存块笔记相关的知识,希望对你有一定的参考价值。
2021-10-21面向对象:动态分配所得的内存块笔记
此笔记中皆是在VC编译器的情况
new和delete
Complex class:
class Complex
{
public :
Complex() {}
private :
double m_real;//实部
double m_imag;//虚部
};
Complex* p = new Complex();
对于Complex p = new Complex();*编译器转化为如下
//1.分配内存,调用malloc(n)函数申请内存
void*mem = operator new(sizeof(Complex));
//2.类型转换
p = static_cast<Complex*>(mem);
//3.构造函数
pc->Complex::Complex(1,2);//Compelx::Complex(pc,1,2),pc一般默认不写,在函数中直接用this来表示
class String
{
public:
String(const char* cstr=0){
if (cstr) {
m_data = new char[strlen(cstr)+1];
strcpy(m_data, cstr);
}else{
m_data = new char[1];
*m_data = '\\0';
}
}
~String(){delete[] m_data;}
private:
char* m_data;
};
String* ps = new String("hello");
delete[] ps;
对于*delete[] p;*编译器转化步骤如下:
//delete: 先调用析构函数再释放内存
//1.调用析构函数
String::~String();
//2.释放内存
operator delete(ps);//内部调用free()函数
动态分配所得的内存块大小
Complex的data部分有两个double类型的变量,内存大小是8字节,实际在VC编译器下申请到的内存大小如下图所示
所以在调试模式下,实际上指针p总共获得的内存大小是64个字节。
除了Complex类的data部分共8个字节(此处一个double4字节),在调试状态下VC编译器额外分配32+4个字节,还有两个在头尾的主要记录整块内存信息的cookie共8字节,加起来一共52字节,因为在VC编译器中,VC给的每一个区块都是16的倍数,所以,给到的最终内存块大小总共大小要是16的倍数,进而此处还要增加12个字节,使52字节变成64字节。
关于除去本身data部分的内存,其余的内存分配不是浪费,是为了更好地回收内存。
关于cookie : 主要是记录分配所得的内存的大小,让系统知道回收这整块内存的大小,表示的都是16进制的数,在此例子中,该整块内存大小为64个字节,转换16进制便是40,最后一位变成1表示这个内存以及分配出去。为什么是16进制呢?因为内存块大小都是16的倍数,由16进制表示的话最后一位的数字必定是0,便于用最后一位数字来标记内存是否分配出去。
如果不是在调试状态下的话,就没有额外分配的32+4字节内存,如下图所示
由于16是16的倍数所以无需补充内存
动态分配所得的array内存大小
Complex* p = new Complex[3];
内存块中会增加4字节来记录array的个数
array new 一定要搭配array delete
如果使用array new一定要搭配array delete,否则容易发生内存泄漏。
在上面的类String动态分配内存中使用array new 即 String ps = new String(“hello”);* 则就要配合使用array delete 即 delete[ ] ps。
如果缺少[ ]执行的是delete ps,则会出现一些指针所指向的内存区域未被清除导致内存泄漏。
String使用array new 时分配的内存大小如下(非调试模式下):
当使用delete是delete ps而不是delete[ ] ps时,析构函数被调用,然后释放内粗——根据cookie的信息判断要删除的A的整块大小,因此A处有无[ ]都会被整块清除掉因为cookie的信息不会因为是不是array delete而变化。然而当有[ ]才会让编译器知道要调用三次析构函数来把每个string object所获得的内存B(a、b、c)清除掉,而没有delete的话,析构函数只被调用一次,只清除掉了A和a,导致剩下的b和c没有被清除掉,从而导致内存泄漏。
Complex与String相比,虽然Complex* p =new Complex[3]中没有指针指向别的内存区域,即使detele p也不会发生内存泄漏,申请的内存也会根据cookie的信息整块删除掉,但是使用了arrray new就要搭配array delete来使用可以以防万一导致内存泄漏,养成好习惯。
知识来源:
侯捷C++面向对象高级开发:8.堆,栈与内存管理
以上是关于2021-10-21面向对象:动态分配所得的内存块笔记的主要内容,如果未能解决你的问题,请参考以下文章