C++ 内存管理
前言
C++兼容C的大多数语法,malloc/calloc/free 在C++也可以继续使用,但是一些场景下无法满足需求,于是提供了new/delete 操作符进行动态内存管理。
一 、C/C++ 内存管理
new/delete 操作自类型
对于操作自定义类型,用malloc或者new申请空间没什么区别,都不会对所申请的内存空间初始化。但malloc需要手动给出所申请空间大小,还需要手动强转,没有new方便。
//malloc申请10个int大小内存
int* ptr1 = (int*)malloc(sizeof(int) * 10);
//free释放
free(ptr1);
//new申请10个int大小内存
int* ptr2 = new int[10];
//delete[] 释放
delete[] ptr2;
new/delete 操作自定义类型
对于操作自定义类型,malloc只申请了空间,并没有对空间进行初始化,free也仅仅释放了空间。new不仅仅申请了空间,还调用了其默认构造初始化 (如果不提供默认构造,则无法通过编译,编译器提供的默认无参构造,我们手动给出的无参构造,参数列表全缺省的构造,都为默认构造) 。delete时,也调用了其析构函数对其进行资源释放。
class Person
{
public:
Person(string name = "张三", int age = 11):_name(name),_age(age) {}
private:
string _name;
int _age;
};
int main()
{
Person* p1 = (Person*)malloc(sizeof(Person) * 10);
Person* p2 = new Person[10];
delete[] p2;
free(p1);
}
注意点:
malloc/free 和 new/delete 一定要成对使用,混合着用很容易引起程序奔溃或者内存泄露,虽然在某些情况不会有问题。
int* ptr1 = (int*)malloc(sizeof(int) * 10);
delete ptr1; // 对于内置类型,正常释放,也不会有内存泄露,不建议这样用
new/delete 底层原理
operator new/operator delete 全局函数
new在底层了调用了operrator new这个全局函数,其底层其实也是调用了malloc申请堆空间,但其对申请空间失败的处理与malloc不同,malloc申请失败返回null,new申请失败则会以抛异常的方式处理。
operator delete 底层也是对free的封装。
new 一共做了两件事,1. 调用operator new申请空间 2. 调用了析构函数。
delete 1. 调用析构函数释放资源,2. operator delete释放空间
我们也可以手动调用operator new /delete 申请,释放空间,其使用方式和malloc free相同。
Person* p2 = (Person*)operator new(sizeof(Person) * 10);
operator delete(p2);
operator new[] / operator delete[]
operator new[] 底层调用operator new 完成N个对象的空间申请,还调用了N次构造函数对所申请空间完成初始化。
operator delete[] 对所要释放空间调用N次析构函数释放对象的资源,底层调用operator delete完成释放。
定位new (replacement-new)
定位new的作用是在已申请的空间上调用构造函数初始化对象。
//malloc只空间,没有完成初始化
Person* p1 = (Person*)malloc(sizeof(Person));
//在已经申请的空间上调用构造函数进行初始化
new(p1)Person("李四",22);
Person* p2 = (Person*)malloc(sizeof(Person) * 3);
for (int i = 0; i < 3; i++)
new(p2 + i) Person(pArr1[i]); //调用拷贝构造对其初始化
面试题:new/delete 和 malloc/free 的区别
- malloc申请空间需要手动给出所申请空间大小,并且需要强转,new只需要给出申请对象的个数。
- malloc不会对申请的空间进行初始化,无论是内置还是自定义类型,而new会对自定义类型调用其构造函数对其初始化,而内置类型不会。
- 从本质上看,new其实就是对malloc的封装+构造函数,delete就是析构+free的封装。
- 从申请失败的处理方式上,malloc申请空间失败返回NULL,new申请失败会以抛异常的方式处理。
斜体样式
|