一、C/C++内存区域划分
![]()
1. 栈又叫堆栈--非静态局部变量/函数参数/返回值等等,栈是向下增长的。
2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。
3. 堆用于程序运行时动态内存分配,堆是可以上增长的。
4. 数据段--存储全局数据和静态数据。
5. 代码段--可执行的代码/只读常量。
二、常见变量存储区域
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | intglobalVar = 1;//全局变量中在静态区
staticintstaticGlobalVar = 1;//静态区
voidTest()
{
staticintstaticVar = 1;//静态区
intlocalVar = 1;//栈区
intnum1[10] = { 1, 2, 3, 4 };//栈区
charchar2[] ="abcd";//栈区,*char2在栈区
constchar* pChar3 ="abcd";//指针在栈区,*pchar3在常量区
int* ptr1 = (int*)malloc(sizeof(int) * 4);//指针在栈区,*ptr1在堆区
int* ptr2 = (int*)calloc(4,sizeof(int));///栈区
int* ptr3 = (int*)realloc(ptr2,sizeof(int) * 4);//栈区
free(ptr1);
free(ptr3);
}
|
三、new和delete
1、new和delete的使用方式
1 2 3 4 5 6 7 8 9 10 11 12 13 | intmain()
{
int* p1 =newint;//在堆区申请一个int大小的空间,不会初始化
int* p2 =newint(0);//申请并初始化为0
deletep1;
deletep2;
int* p3 =newint[10];//在堆区申请一块10个int大小的空间,未初始化
int* p4 =newint[10]{ 1,2,3,4 };//初始化为{1,2,3,4,0,0,0,0,0,0}
delete[] p3;
delete[] p4;
return0;
}
|
注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],一定要匹配起来使用。
2、new、delete和malloc、free的区别
1、对于内置类型,没有区别。
2、new和delete是C++的关键字/操作符,而malloc和free是C语言的库函数。
3、对于自定义类型,相比于malloc和free,new和delete会额外调用类中的构造函数和析构函数。
4、malloc的返回值是void*,使用时需要强转,new后边跟的是空间的类型,所以new不需要强转。
5、malloc失败返回空指针,需要判空;new失败抛异常,需要捕获异常。
3、new的原理
new等于operator new()+构造函数。operator new()不是new运算符的重载,因为参数没有自定义类型。它是一个库里的全局函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | void*__CRTDECL operatornew(size_tsize) _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 类型异常
staticconststd::bad_alloc nomem;
_RAISE(nomem);
}
return(p);
}
|
从底层代码可以看出operator new()是对malloc的封装,如果malloc失败,将会抛出异常。
4、delete的原理
delete等于operator delete()+析构函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | //operator delete: 该函数最终是通过free来释放空间的
voidoperatordelete(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 );//调用free()
__FINALLY
_munlock(_HEAP_LOCK);/* release other threads */
__END_TRY_FINALLY
return; }
//free的实现
#define free(p) _free_dbg(p, _NORMAL_BLOCK)
|
从底层代码可以看出operator delete()调用了free。
所以针对内置类型或无资源的类对象delete时,使用delete和free效果相同。但对于有资源需要释放的对象时,直接使用free虽然释放了对象的空间,但对象内部的资源还未被清理,导致内存泄漏!这种情况必须使用delete。
5、new T[N]原理
1、new T[N]调用operator new[]
2、operator new[]调用operator new完成N个对象空间的开辟。
3、调用N次构造函数完成N个对象的初始化。
6、delete[]原理
1、调用N次析构函数完成N个对象资源的清理工作。
2、调用operator delete[]
3、operator delete[]调用operator delete完成整段空间的释放。
四、定位new
1、定位new的概念
![]()
对于一个类,我们可以显式的去调用类的析构函数,但是不能显式调用构造函数,那么使用定位new,就可以显式调用类的构造函数,对一块空间重新初始化。