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次析构函数???

C++内存管理(内含面试题:C和C++的区别,new 和delete的底层原理)
深度剖析
C++内存管理(内含面试题:C和C++的区别,new 和delete的底层原理)

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的区别)

  1. new/delete是操作符,malloc/free是函数。(本身性质不同**
  2. .new在使用时会调用malloc先开空间在调用构造函数进行初始化,delete会先调用析构函数清理对象,然后在调用free释放空间。(申请内存底层不同是否调用构造函数和析构函数*

  3. malloc在堆上开空间,new是在*存储区(堆或者 静态存储区)开空间。(开辟空间的位置不同*

  4. malloc开空间的时候需要指定空间的大小,而new只需要类型名(AA a1=new AA();)(开辟空间大小是否要指定**

  5. malloc开辟的空间可以给 单个对象使用,也可以给对象数组使用释放交给free;new 给对象数组开空间使用new[],对应释放使用delete[].(给对象和对象数组开辟空间的不同)

  6. malloc申请空间成功返回void*的指针,失败返回NULL;new 申请对象空间成功后返回对象指针,失败会抛异常(成功返回值不同,失败返回的也不同*

  7. 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++中就可以。

C++中有inline、friend(友元)