下图是C++的内存储存管理的方式
由图不难得知,局部变量是储存在栈中的,而malloc,calloc,realloc开辟出来的空间是储存在堆中的,全局数据和静态变量储存在数据段中,也叫静态区.代码段存的是可执行代码和只读常量。
C 语言中动态内存管理方式: malloc/calloc/realloc/free C++ 内存管理方式 语言内存管理方式在 C++ 中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因 此 C++ 又提出了自己的内存管理方式: 通过 new和delete 操作符进行动态内存管理 使用方法:#include<iostream>
using namespace std;
void test()
{
int* p1 = new int;//动态申请一个int 类型的空间
int* p2 = new int(1); //动态申请一个int 类型的空间并初始化为1
cout << *p2 << endl;
int* p3 = new int[3]; //动态申请三个int 类型的空间
int* p4 = new int[3] {1,2,3}; //动态申请三个int 类型的空间并初始化为1,2,3
for (int i = 0; i < 3; i++)
{
cout << *(p4+i) << endl;
}
delete p1;
delete p2;
delete[] p3;
delete[] p4;
}
int main()
{
test();
return 0;
}
运行结果
未执行delete时 执行delete后释放空间 new 和 delete 操作自定义类型 自定义类型中使用new和delete会自动申请类型大小的空间和自动调用构造函数和相应的析构函数并释放空间#include<iostream>
using namespace std;
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a = 0)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* P1 = new A;
A* P2 = new A(1);
A* P3 = new A[3]{ 1,2,3 };
delete P1;
delete P2;
delete[] P3;
}
运行结果表明确实调用了构造函数和析构函数
注意:在申请自定义类型的空间时, new 会调用构造函数, delete 会调用析构函数,而 malloc 与 free 不会 。 operator new 与 operator delete 函数 new 和 delete 是用户进行 动态内存申请和释放的操作符 , operator new 和 operator delete 是 系统提供的 全局函数 , new 在底层调用 operator new 全局函数来申请空间, delete 在底层通过 operator delete 全局函数来释放空间。 /* operator new :该函数实际通过 malloc 来申请空间,当 malloc 申请空间成功时直接返回;申请空间 失败,尝试执行空 间不足应对措施,如果改应对措施用户设置了,则继续申请,否 则抛异常。 */ void * __CRTDECL operator new ( size_t size ) _THROW1 ( _STD bad_alloc ) { // try to allocate size bytes void * p ; while (( p = malloc ( size )) == 0 ) if ( _callnewh ( size ) == 0 ) { // report no memory // 如果申请内存失败了,这里会抛出 bad_alloc 类型异常 static const std::bad_alloc nomem ; _RAISE ( nomem ); } return ( p ); } /* operator delete: 该函数最终是通过 free 来释放空间的 */ void operator delete ( void * pUserData ) { _CrtMemBlockHeader * pHead ; RTCCALLBACK ( _RTC_Free_hook , ( pUserData , 0 )); if ( pUserData == NULL ) return ; _mlock ( _HEAP_LOCK ); /* block other threads */ __TRY /* get a pointer to memory block header */ pHead = pHdr ( pUserData ); /* verify block type */ _ASSERTE ( _BLOCK_TYPE_IS_VALID ( pHead -> nBlockUse )); _free_dbg ( pUserData , pHead -> nBlockUse ); __FINALLY _munlock ( _HEAP_LOCK ); /* release other threads */ __END_TRY_FINALLY return ; } /* free 的实现 */ #define free(p) _free_dbg(p, _NORMAL_BLOCK) 通过上述两个全局函数的实现知道, operator new 实际也是通过 malloc 来申请空间 ,如果 malloc 申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施 就继续申请,否则就抛异常。 operator delete 最终是通过 free 来释放空间的 。 new 和 delete 的实现原理 内置类型 如果申请的是内置类型的空间, new 和 malloc , delete 和 free 基本类似,不同的地方是: new/delete 申请和释放的是单个元素的空间, new[] 和 delete[] 申请的是连续空间,而且 new 在申 请空间失败时会抛异常, malloc 会返回 NULL 。 自定义类型 new 的原理 1. 调用 operator new 函数申请空间 2. 在申请的空间上执行构造函数,完成对象的构造 delete 的原理 1. 在空间上执行析构函数,完成对象中资源的清理工作 2. 调用 operator delete 函数释放对象的空间 new T[N] 的原理 1. 调用 operator new[] 函数,在 operator new[] 中实际调用 operator new 函数完成 N 个对 象空间的申请 2. 在申请的空间上执行 N 次构造函数 delete[] 的原理 1. 在释放的对象空间上执行 N 次析构函数,完成 N 个对象中资源的清理 2. 调用 operator delete[] 释放空间,实际在 operator delete[] 中调用 operator delete 来释 放空间 定位 new 表达式 (placement-new) 定位 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;
}
malloc/free
和
new/delete
的区别
malloc/free
和
new/delete
的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地
方是:
1. malloc
和
free
是函数,
new
和
delete
是操作符
2. malloc
申请的空间不会初始化,
new
可以初始化
3. malloc
申请空间时,需要手动计算空间大小并传递,
new
只需在其后跟上空间的类型即可,
如果是多个对象,
[]
中指定对象个数即可
4. malloc
的返回值为
void*,
在使用时必须强转,
new
不需要,因为
new
后跟的是空间的类型
5. malloc
申请空间失败时,返回的是
NULL
,因此使用时必须判空,
new
不需要,但是
new
需
要捕获异常
6.
申请自定义类型对象时,
malloc/free
只会开辟空间,不会调用构造函数与析构函数,而
new
在申请空间后会调用构造函数完成对象的初始化,
delete
在释放空间前会调用析构函数完成
空间中资源的清理释放
补充:free和new不能搭配使用,否则有些情况下会报错
#include<iostream>
using namespace std;
class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a = 0)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
int main()
{
A* P3 = new A[3]{ 1,2,3 };
free(P3);
return 0;
}
这个代码中虽然释放掉了空间,但是没有正确调用析构函数会导致崩溃
标签:free,malloc,管理,C++,空间,内存,operator,new,delete From: https://blog.csdn.net/2301_79389054/article/details/143206463