关于new delete和placement new,placement delete

问题:

在看stl源码的时候,发现new 还可以这么调用:

T* tmp = (T*)(::operator new((size_t)(sizeof(T) * n)));
这个调用很类似于malloc这样的形式,而且参数是以字节为主的,这和我平时使用的new 不一样的,那么::operator new是不是更加底层的函数,也就是上层的new其实是通过调用这个函数来申请空间的呢?

解答:

首先在这里需要明白一个前提:

operator new /operator delete 和 new operator / delete operator这两种的区别,我们通常使用的是new operator/delete operator,而我们通常在类中重载的是operator new / operator delete.在区别就是前者是库函数,而后者是操作运算符;

对于两者的区别:

new operator/delete operator:这两个操作里面包含了两个过程:

  1. 申请空间.
  2. 在申请好的空间上调用对象的构造函数进行初始化的.

而delete则是析构+释放内存,而这就是它们的作用的;而这两者是不能被重载的,网上的解释说这两者是不能被重载的,C++标准规定这两者的行为不应该也不能够被改变的;

operator new/operator delete:其实这两个有点类似于C中的malloc和free,因为他们只是负责申请空间和释放空间,而且他们接受的参数也是字节数,这和malloc和free几乎是一模一样,不过他们的使用必须要配对着,new出来的内存必须用delete才能释放掉;而且他们可以被用来重载,通常在类域中被重载,从而达到高效的内存分配。

new operator的过程:

1.调用operator new来申请空间:ptr = ::operator new(sizeof(T))

2.然后调用构造函数进行初始化;

而就是这2步是不能变化的,这也保证了new operator的行为是不变的,如果我们对operator new 进行重载的话,那么就可以改变new operator 的第一步,编译器会调用类中的重载过的new,与此同时,我们也要重载了operator delete,因为要对应起来,这样的话不会导致内存泄漏;

 
程序和运行结果表示了我的想法,而且如果你自己不重载operator delete的话,那么编译器会自动的调用全局的delete,也就是::operator delete


对operator new的重载注意点:

  1. 返回值一定要为void*(其实这比较好理解,因为这个只是用来申请空间的,而没有初始化,所以返回void*是应该的) 
  2. 参数为size,是字节数
  3. 重载时可以携带其他的参数(如果你给与了参数,那么你在使用new的时候,必须写上你的参数,比如new("hello") int(5));


2.placement new(定义:如果operator new 接受除size以后的参数,那么这个operator new 就是placement new)


对于这个我们平常可以看见的就是有这样的语句

new (ptr) int(5);

对于这样的语句,可能比较奇怪,因为通常我们都是这么使用new的,new int(5),其实上面的就是placement new;

placement new:其实是operator new的一个重载版本,但是关键在于它是重载operator new 的一个标准、全局的版本,它不能够被自定义的版本代替

其实对于这句话我还是不能很好的理解的,做一个实验吧?


这是我在全局范围内定义了一个placement new,当然运行的结果是这个函数已经定义过了,所以error;因为这是一个全局范围内的,而正式的placement new以前在标准库的某一个地方定义过来了,所以不能我重新定义;

关于placement new 的效果就是在已经存在的内存块上构造一个对象的;new(ptr) A(),这就表示在ptr指定的地方构造A对象的;

按书上所说,这个特殊的placement new 是定义在<new>文件中的,它的原型就是:


其实这个函数真的很简单,只是很简单的返回了p这个参数,关于这个问题其实我也不是很明白?不过书上的意思是说这个new可以调用构造函数,所以比较好。

对于placement new这样的new来说,必须要匹配对应的placement delete,也就是附带的参数要和new 是一样的,而这样的delete的用处只有一个,当new在分配内存的时候发生异常,这个时候编译器会寻找一个delete来处理这个问题,如果没有定义相应的placement delete的话,这个时候编译器就什么都不做了,如果定义了,那么就会使用这个delete来做一些还原的工作的;placement delete除了这个工作,其他没有任何作用,对于一个指针使用delete是绝对不会调用placement delete的,绝对不会,不会;

对于一个指针使用delete来说,通常调用就2个,一个是全局的delete的,一个是类中的operator delete;

最后看一些关于全局的placement delete的源代码


可以看出来,它其实什么都没有做的;在深入探索

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值