C++内存管理(内含面试题:C和C++的区别,new 和delete的底层原理)
1、new/delete、new[]/delete[]
new、delete是操作符,用来分配空间和清理对象的。new[]、delete[]是来为对象数组分配空间和清理对象的。
int* p1=new int;//分配一个int大小的空间
int* p2=new int(3);//分配一块空间,并将空间初始化成3.
int* p3=new int[3];//分配3个int对象的空间。
2、底层原理
其他内存管理接口 operator new/operator delete、operator new[]/operator delete[]
!!!operator …不是new/delete的重载!!!
总结:
operator new/operator delete、operator new[]/operator delete[]与malloc/free用法一样。
负责分配空间/释放空间,但是不会调用构造函数和析构函数来初始化/清理对象。
实际上operator new/operator delete是malloc/free的一层封装。
new 做了两件事
1. 调用operator new分配空间。
2. 调用构造函数初始化对象。
delete做了两件事
1. 调用析构函数清理对象。
2. 调用operator delete释放空间。
new [N]
1. 调用operator new分配空间。
2. 调用N此构造函数来初始化对象。
delete[N]
1. 调用N次析构函数清理对象。
2. 调用operator delete释放空间。
????如何确定是要调用N次析构函数???
深度剖析
3、使用时注意事项:(匹配使用)主要在于是否在正确的位置调用析构函数。
只有自定义构造函数和析构函数的自定义类型,才会多开四个字节。
只限于自定义类型:
(1)不会崩溃,虽然没有调用析构函数
AA* p0=new AA;
free p0;
(2)程序会崩溃,因为delete[]在对象使用完成后会默认将指针-4,取到最前面的位置调用析构函数,但是构造对象的时候是从当前位置开始的,所以就会出现指针越界,程序就会崩溃。
AA* p1=new AA;
delete[] p1;
(3)程序会崩溃,free不会偏移4个字节,释放位置错误
AA* p2=new AA[10];
free p2;
(4)程序会崩溃,虽然delete只析构一次,但是这不是程序崩溃的原因,主要原因是 释放位置错误
AA* p3=new AA[10];
delete p3;
内置类型假如不匹配也不会崩溃,是由于内置类型在开空间的时候不会多开四个字节!!!
5、重要面试题:C和C++的的区别与联系
联系:C++兼容了大部分C的语法。
内存管理方面的不同(new/delete、malloc/free的区别)
- new/delete是操作符,malloc/free是函数。(本身性质不同**)
.new在使用时会调用malloc先开空间在调用构造函数进行初始化,delete会先调用析构函数清理对象,然后在调用free释放空间。(申请内存底层不同是否调用构造函数和析构函数*)
malloc在堆上开空间,new是在自由存储区(堆或者 静态存储区)开空间。(开辟空间的位置不同*)
malloc开空间的时候需要指定空间的大小,而new只需要类型名(AA a1=new AA();)(开辟空间大小是否要指定**)
malloc开辟的空间可以给 单个对象使用,也可以给对象数组使用释放交给free;new 给对象数组开空间使用new[],对应释放使用delete[].(给对象和对象数组开辟空间的不同)
malloc申请空间成功返回void*的指针,失败返回NULL;new 申请对象空间成功后返回对象指针,失败会抛异常(成功返回值不同,失败返回的也不同*)
malloc开辟的空间如果不够用可以使用realloc来扩大空间,但是new不可以。(能否扩容)
C++有了面向对象的特性
具有面向对象的特性:继承封装多态
C++有了STL
C的struct和C++的class
C中struct是结构体,C++对于strcut进行了扩展,再C++中还可以当做类使用,唯一不同的是默认访问修饰符不同。C语言中默认是public而C++中默认是private.
C语言不支持重载,C++支持重载
C++之所以支持重载是因为名字修饰不同,不是单单利用函数名不同来区别是否可以重载。
int Add(int a,double b);
在汇编语言下就会被处理成 _Add_int_double,有了这一层修饰,那么就可以保证函数名相同但是参数列表不同,实现了重载。
C++有引用
见面试题:引用和指针的区别
const 修饰变量的不同
C中变量如果使用const修饰那么就相当于常变量,const修饰的变量仍然不能用于定义数组的大小,但是C++中就可以。