专栏:C/C++
个人主页:HaiFan.
专栏简介:本章为大家带来C++的内存管理方式。
当程序运行的时候,操作系统会为其分配一块内存,该内存被分为以下几个部分:
C语言中的动态内存管理方式是: malloc,realloc,calloc,free
,相信这四个函数大家应该不陌生,在数据结构部分,经常用这几个函数去动态开辟空间。
int main()
{
int* a = (int*)malloc(sizeof(int));
if (a == NULL)
{
perror("malloc fail");
exit(-1);
}
int* tmp = (int*)realloc(a, sizeof(int) * 4);
if (tmp == NULL)
{
perror("realloc fail");
exit(-1);
}
a = tmp;
int* b = (int*)calloc(0, sizeof(int));
free(a);
a = NULL;
free(b);
b = NULL;
return 0;
}
简单复习一下这几个函数。malloc用于申请一块空间,realloc用于给当前的空间扩容(异地扩容或者原地扩容),calloc用于申请一块空间并初始化。
这是C语言的内存管理方式。
C语言的内存管理方式可以在C++中继续使用,但是用起来比较麻烦,所以C++提出了自己的内存管理方式-----------new和delete操作符进行内存管理。
int main()
{
int* a = new int;
int* a1 = new int(1);
delete a;
delete a1;
return 0;
}
a和a1的区别是什么?
从监视窗口中可以看出,a1被初始化了,而a没有。new int是动态申请一个int类型的空间,new int(1)是动态申请一个int类型的空间并初始化。
int main()
{
int* a = new int[3];
int* a1 = new int[3]{ 1,2,3 };
delete[] a;
delete[] a1;
return 0;
}
第一个不会给数组初始化,而第二个会给数组初始化,对于使用 new 运算符分配的动态数组,如果不进行完全初始化,则剩余的元素将默认为 0。
如果想让数组全为0,则可以
int* a1 = new int[5]();
class A
{
public:
A(int a)
:_a(a)
{
cout << "A(int a)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* a1 = new A(1);
delete a1;
A* a2 = (A*)malloc(sizeof(A));
free(a2);
return 0;
}
输出结果是 A(int a) ~A()
从结果中可以看出,new/delete和malloc/free最大区别是 前者对于自定义类型除了开空间,还会调用构造函数和析构函数。
定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象。
使用格式:new (place_address) type或者new (place_address) type(initializer-list)
place_address必须是一个指针,initializer-list是类型的初始化列表
使用场景:
定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。
class A
{
public:
A(int a = 0)
: _a(a)
{
cout << "A():" << this << endl;
}
~A()
{
cout << "~A():" << this << endl;
}
private:
int _a;
};
// 定位new/replacement new
int main()
{
// p1现在指向的只不过是与A对象相同大小的一段空间,还不能算是一个对象,因为构造函数有执行
A* p1 = (A*)malloc(sizeof(A));
new(p1)A; // 注意:如果A类的构造函数有参数时,此处需要传参
p1->~A();
free(p1);
A* p2 = (A*)operator new(sizeof(A));
new(p2)A(10);
p2->~A();
operator delete(p2);
return 0;
}
内存泄漏是指分配的堆内存没有被释放或被错误的方式释放,导致应用程序无法再次访问这些内存。由于内存泄漏占用了大量的系统内存资源,因此它会损害应用程序的性能和可靠性,并可能导致应用程序最终崩溃。
忘记delete内存。忘记释放动态内存会导致内存泄漏问题,因为这种内存不可能被归还给自由空间了。查找内存泄漏错误是非常困难的,因为通常应用程序运行很长时间后,真正耗尽内存时,才能检测到这种错误。