C++内存管理

一、内存分布

C++内存管理_第1张图片

1.栈又叫堆栈--非静态局部变量/函数参数/返回值等等都是建立存放在栈中,栈是向下增长的。

2. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口 创建共享共享内存,做进程间通信。

3. 堆用于程序运行时动态内存分配,例如c中用malloc所开辟的空间就是在堆中,堆是可以上增长的。

4. 数据段,也叫静态区,存储全局数据和静态数据都是建立在静态区内。

5. 代码段,用const修饰常变量或者常量都建立在代码段,还有可执行的代码/只读常量等等。

二、内存管理方式 new / delete

1.new和delete

(1) new

a.用处:

new可以用来想堆申请空间,类似于malloc,用法上:

int* a = new int ;  //向堆申请一个整形的空间

int *a = new int(5); //向堆申请一个整形的空间,并初始化为5

int *a = new int[5];//向堆申请五个整形的空间,没有初始化

int *a = new int[5] {1,2,3}; //想堆申请五个整形空间,对前三个分别初始化为1,2,3,其余默认初始化为0

以上例子展示了new的用法,以及细节,可以看到,与malloc有所不同

b.new和malloc的区别:

1. new可以对开辟的空间进行初始化,malloc无法初始化

2.new后面带上类型,返回的地址不需要类型转换

3.new对内置类型的初始化上与malloc相比没有太多优势,但如果是对自定义类型,new会自动调用自定义类型的析构函数,再开辟空间,这是C++中new取代malloc的关键

(2) delete

用处:

delete和new配套使用,类似于free,用于释放new在堆申请开辟的空间,注意只能配套使用,交叉使用容易出现不可知的错误

用法:

delete a;  //若a此时只有单位变量的指针,则可以直接在delete后面加上指针名

delete[ ] a;//若a是一个变量数组的指针,则需要在delete后面加上[ ]

delete在释放自定义变量前,会先调用类的析构函数,这是比起free最大的优势

2.operator new 和 operator delete

介绍:

operator new 和 operator delete 虽然都带有operator,但和运算符重载没有任何关系,性质上是两个系统函数,new 和 delete 的底层也是通过这两个函数实现的,这两个函数的底层实际是对malloc和free的封装。

C++内存管理_第2张图片

代码

/*
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;
}

三、定位new

介绍:

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如 果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

使用格式:

new(类型指针)type(初始化列表);

例子:

A* p2 = (A*)operator new(sizeof(A));
 new(p2)A(10);
 operator delete(p2);

四、常见相关面试题

1.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在释放空间前会调用析构函数完成 空间中资源的清理

2.什么是内存泄漏,内存泄露的危害是什么

什么是内存泄漏:

内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况。内 存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对 该段内存的控制,因而造成了内存的浪费。

内存泄漏的危害:

长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现 内存泄漏会导致响应越来越慢,最终卡死。

总结:

本篇讲的是,在C++中新添加的,用于内存管理的操作符new和delete,该操作符的相对于c中malloc和free的优势,以及相关的一些知识点总结。

你可能感兴趣的:(jvm,c++)