02.02_111期_C++_数据内存分布笔记
operator new 和 operator delete是系统提供的全局函数
operator new是对malloc的封装
operator deleter是对free的封装
实际上在写出int* p2 = new int;这样的代码的时候,
由于new是一个操作符,所以在编译的时候要转成对应的指令
转成的指令就是operator new,这个operator new这个函数本质上和malloc是一样的
写出ListNode* node1 = new ListNode(1);这样的代码的时候,
new会申请空间,此时new转成的汇编指令中会先执行 operator new 和 再调用构造函数
在写出int* p2 = new int[10];这样的代码的时候
应该把new[10]看作是一个操作符,在编译的时候转成的汇编指令是operator new[]
operator new[]会申请空间,其实现是operator new申请了10个int空间的函数
写出ListNode* node2 = new ListNode[10];这样的代码的时候,
new会申请空间,此时new转成的汇编指令是 operator new[]
此时的operator new[]实际上是先operator new 再调用构造函数,这样反复10次以后
但是需要注意的是申请的空间是4 + 10 * sizeof(ListNode) 个字节的空间
多开出来的4个字节的空间放的是对象个数,保证在使用delete[]进行释放时
能够精准的释放之前申请的空间,delete[]在使用时不带参数
之所以只有在释放自定义类型的空间时才会多申请4个字节(x86)
这是因为需要对每个申请自定义类型的对象都调用析构函数
如果这个类恰好是栈类,那么就需要把 在堆上申请的数组空间全部释放,
那么释放多少次数组空间呢?只有通过这4个字节的空间中所存放的内容才能确定
sizeof 和 strlen在底层上的不同
sizeof 作为一个操作符,在编译时就会转成一堆指令,
将内置类型或自定义类型按照规则算出所占字节数
strlen 在生成可执行文件以后,在运行过程中按照库函数的逻辑返回一个值
所以这两者的实现阶段都是不一样的
对于申请了多个自定义对象在堆区后,要释放这些自定义对象所申请的空间
应该使用delete[]
下面这两行代码说明了,
new在申请了一块空间来放Stack中的_a, _top, _capacity之后
如果要释放,必须是先释放_a指向的那块申请的整型数组空间
然后再释放pst指向的自定义类型的空间,
也就是说 delete是先将类中申请的空间释放(调用析构函数)
再把这个类所占的空间进行释放
1 有关c++内存分配堆栈
1.1 栈区主要存在局部变量和函数参数,其空间的管理由编译器自动完成,无需手动控制,堆区是自己申请的空间,在不需 要时需要手动释放
1.2栈区先定义的变量放到栈底,地址高,后定义的变量放到栈顶,地址低,因此是向下生长的,堆区则相反
1.3 频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
1.4 32位系统下,最大的访问内存空间为4G,
2
2.1 堆大小受限于操作系统,而栈空间一般有系统直接分配
2.2 频繁的申请空间和释放空间,容易造成内存碎片,甚至内存泄漏,栈区由于是自动管理,不存在此问题
2.3 堆无法静态分配,只能动态分配
2.4栈可以通过函数_alloca进行动态分配,不过注意,所分配空间不能通过free或delete进行释放
3 下面代码的运行结果
ClassA *pclassa=new ClassA[5];
delete pclassa;
申请对象数组,会调用构造函数5次,delete由于没有使用[],此时只会调用一次析构函数,但往往会引发程序崩溃
4
4.1 new会申请空间,同时调用构造函数初始化对象,malloc只做一件事就是申请空间
4.2 new/delete与malloc/free最大区别就在于是否会调用构造函数与析构函数
4.3 new是保留字,不需要头文件,malloc是库函数,需要头文件malloc.h,只是平时这个头文件已经被其他头文件所包含了,用的时候很少单独引入,故错误
4.4 new是操作符,malloc是函数
5 设已经有A,B,C,D4个类的定义,程序中A,B,C,D析构函数调用顺序为
C c;
void main()
{
A*pa=new A();
B b;
static D d;
delete pa;
}
全局变量和全局静态变量最先定义,局部静态变量之后定义,局部变量最后定义
局部自定义类型最先析构,局部静态自定义类型之后析构,全局或全局静态自定义类型最后析构
6 下面程序的运行结果
char* p = new char[100];
delete p;
对于内置类型,并不存在构造函数和析构函数这一个环节,所以即使new char [100] 和 delete不匹配,也可以使用上述代码进行释放