Cpp05 — 内存管理

内存管理

代码是以文件的形式存储在磁盘上的。

不是说是代码就会加载到代码段,而是代码编译好的二进制指令代码会加载到代码段,然后程序中main函数执行时就是在代码段取指令来执行。栈和堆上的数据是运行时才建立的。

常量区是有硬件保护的,只要去访问,就会报错

new、delete、malloc、free

new、malloc

new是一个操作符,malloc是函数

int* p1 = new int;//申请1个int

int* p2 = new int[5];//申请有5个int元素的数组

int* p3 = new int(5);//申请1个int对象,初始化为5

new不会初始化,除非有指定。

C++98不支持new时初始化数组,C++11支持

int* p4 = new int[5]{1,2,3,4,5};

A* p3 = new A[2]{A(1), A(2)};

?注意:数量要匹配,不会帮补0的

C++没有和realloc相关的功能的。

delete、free

delete p1;

delete []p2;//释放多个空间,[]中不用写东西

new和delete数量要匹配,不匹配有时候会报警告。

关键字、操作符:new、delete   函数:malloc、free

对于内置类型:new\delete与malloc\free没有本质区别,只是new和delete用法简化了一点。

对于自定义类型:有很大的区别。new对于自定义类型不仅会开空间,还会去调用它的构造函数去初始化,而malloc没有。(delete会调用其析构函数然后释放空间)

区别:

1.new在申请空间时还会调用其构造函数初始化,不提供默认构造函数的话会报错,即使没有,也可以传参,传了就没错了。

2.delete调用析构函数清理对象中的资源,然后释放空间

结论:new/delete是为内置类型准备的,不仅在堆上申请出来,还会调用构造和析构清理

3.malloc失败是返回NULL,一般不会失败,除非开的空间太大了,或者内存不够了,cout打印char*时,打印出来的不是地址,而是字符串,int*那些的不会出现这样的问题,因为会觉得它是指针。而new失败是抛异常,new失败不需要检查返回值,因为它失败是抛异常,异常是面向对象语言处理错误的一种方式,与继承和多态有关

因为申请的是虚拟内存,所以与电脑配置无关,虚拟内存的大小都是4G

free之后,数据还在,只是我们没有它的访问权限了,没有对它直接使用的权限了。

先定义的先构造、后析构

底层原理

其实new的底层是调用了两个函数,即调用operator new去堆上开空间,调用构造函数去初始化,这里的operator new不是对new的重载,而是一个全局函数,其底层是调用malloc开空间。

operator new存在的意义:封装malloc,帮助new开空间,为什么不直接调malloc呢?这样处理符合C++new的失败机制(失败抛异常)。

(其实operator new就可以了,只是为了成一对才有operator delete)

operator new我们也可以直接使用,其实和new是一样的

重载operator new和operator delete,比如我们想检测内存泄漏,重载一下就可以

::域作用限定符,如果没写的话还是调的是库里的,调用的时候可以这么调,建议是对new和delete进行宏替换,这样就会调到它们

原理:

/*
operator new:该函数实际通过malloc来申请空间,当malloc申请空间成功时直接返回;申请空间失败,尝试执行空间不足。应对措施,如果应对措施用户设置了,则继续申请,否则抛异常。即operator new存在的意义是:帮助new开空间,且封装malloc(为了符合C++new的失败抛异常机制)
*/

/*
operator delete: 该函数最终是通过free来释放空间的 
*/

/*
free的实现 
*/
#define   free(p)               _free_dbg(p, _NORMAL_BLOCK)

通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果 
malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。

重载:

// 重载operator delete,在申请空间时:打印在哪个文件、哪个函数、第多少行,申请了多少个 
字节
void* operator new(size_t size, const char* fileName, const char* funcName, 
size_t lineNo)
{
void* p = ::operator new(size);
cout << fileName << "-" << funcName << "-" << lineNo << "-" << p << "-" 
<< size << endl;
return p; 
}
// 重载operator delete,在释放空间时:打印再那个文件、哪个函数、第多少行释放
void operator delete(void* p, const char* fileName, const char* funcName, 
size_t lineNo)
{
cout << fileName << "-" << funcName << "-" << lineNo << "-" << p << 
endl;
    ::operator delete(p); 
}
int main() 
{
// 对重载的operator new 和 operator delete进行调用
int* p = new(__FILE__, __FUNCTION__, __LINE__) int; 
operator delete(p, __FILE__, __FUNCTION__, __LINE__); 
return 0;
}
// 上述调用显然太麻烦了,可以使用宏对调用进行简化
// 只有在Debug方式下,才调用用户重载的 operator new 和 operator delete
#ifdef _DEBUG
#define new new(__FILE__, __FUNCTION__, __LINE__)
#define delete(p) operator delete(p, __FILE__, __FUNCTION__, __LINE__) 
#endif
int main() 
{
int* p = new int; 
delete(p); 
return 0;
}

重载一个类专属的operator new

当一个结点需要被频繁开辟,需要频繁申请,效率就比较低,语言里面有一个池化技术,我们可以申请一个内存池。

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

语法使用的区别、本质功能的区别

 

如果原地扩,p2和p3是相等的,释放p3相当于p2原来的也被带走了,异地扩的话,realloc也把之前的给释放掉了。

 

定位new表达式

定位new是在已有内存空间中调用构造函数初始化一个对象。即创建空间后,想对已创建的对象进行初始化时使用。例如在内存池会用到,因为内存池就是开好的空间,我们可以用定位new来调整

使用格式:new(place_address)type或new(place_address)type(initializer_list)

operator new[]和operator new不一样,一个是针对多个,一个是单个

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

列宁格勒的街头

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值