new 、operator new 和 placement new
一、原生operator new
我们先从原生operator new开始。考虑如下代码,它用来分配5个int型的空间并返回指向他们的指针[1]:
int* v = static_cast<int*>(::operator new(5 * sizeof(*v)));
当像如上的调用,operator new扮演原生的内存分配角色,类似malloc。上面等价于:
int* v = static_cast<int*>(malloc(5 * sizeof(*v)));
释放用operator new分配的内存用operator delete:
::operator delete(v);
二、placement new的含义
placement new 是重载operator new 的一个标准、全局的版本,它不能够被自定义的版本代替(不像普通版本的operator new 和 operator delete能够被替换)。
void *operator new( size_t, void *p ) throw() { return p; }
placement new的执行忽略了size_t参数,只返还第二个参数。其结果是允许用户把一个对象放到一个特定的地方,达到调用构造函数的效果。
和其他普通的new不同的是,它在括号里多了另外一个参数。比如:
Widget * p = new Widget; - - - - - - - - - //ordinary new
pi = new (ptr) int; //placement new
括 号里的参数ptr是一个指针,它指向一个内存缓冲器,placement new将在这个缓冲器上分配一个对象。Placement new的返回值是这 个被构造对象的地址(比如括号中的传递参数)。placement new主要适用于:在对时间要求非常高的应用程序中,因为这些程序分配的时间是确定 的;长时间运行而不被打断的程序;以及执行一个垃圾收集器 (garbage collector)。
三、new 、operator new 和 placement new 区别
new :不能被重载,其行为总是一致的。它先调用operator new分配内存,然后调用构造函数初始化那段内存。
operator new:要实现不同的内存分配行为,应该重载operator new,而不是new。
delete和operator delete类似。
delete首先调用对象的析构函数,然后调用operator delete释放掉所使用的内存。
placement new:只是operator new重载的一个版本。它并不分配内存,只是返回指向已经分配好的某段内存的一个指针。因此不能删除它,但需要调用对象的析构函数。
四、 new 操作符的执行过程
(1). 调用operator new分配内存 ;
(2). 调用构造函数生成类对象;
(3). 返回相应指针。
operator new 就像operator+一样,是可以重载的。如果类中没有重载operator new,那么调用的就是全局的::operator new来完成堆的分 配。同理,operator new[]、operator delete、operator delete[]也是可以重载的,其实 placement new也是operator new的一个重载的版本,只是很少用而已。如果你想在已经分配的内存中创建一个对象,使用new时行不通 的。也就是说placement new允许你在一个已经分配好的内存中(栈或者堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配 好的内存缓冲区的的首地址。
五、 Placement new 存在的理由
(1).用Placement new 解决buffer的问题
问 题描述:用new分配的数组缓冲时,由于调用了默认构造函数,因此执行效率上不佳。若没有默认构造函数则会发生编译时错误。如果你想在预分配的内存上创建 对象, 用缺省的new操作符是行不通的。要解决这个问题,你可以用placement new构造。它允许你构造一个新对象到预分配的内存上。
(2).增大时空效率的问题
使用new操作符分配内存需要在堆中查找足够大的剩余空间,显然这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。
placement new 就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存,内存分配的时间是常数;而且不会出现在程序运行中途出现内 存不足的异常。所以,placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序。
六、 实例
#include<stdio.h> char* buffer[];
class LinearAllocator
{
public:
void* alloc(size_t){
return buffer;
}
}; class DisplayListOp {
public:
DisplayListOp(int a, int b){
printf("a = %d b = %d\n", a, b);
} static void operator delete(void* ptr,int param) {
printf("delete param = %d\n", param);
}; static void operator delete(void* ptr) {
printf("delete no param \n");
}; static void* operator new(size_t size, LinearAllocator& allocator,int param) {
printf("operator new param = %d\n", param);
return allocator.alloc(size);
}
}; int main()
{
LinearAllocator lineAlloc;
DisplayListOp* pw = new (lineAlloc, ) DisplayListOp(,);
delete pw; return ;
}
结果
operator new param =
a = b =
delete no param
由上面的例子及结果可以推断
new (lineAlloc, 11) DisplayListOp(12,13)
上述表达式中 第一个括号内不参数传递给operator new 函数, 第二个括号内的参数传递给类的构造函数
如果 static void operator delete(void* ptr)操作,则采用该重载函数
参考:
[1]. C++ 内存分配(new,operator new)详解 : http://blog.csdn.net/wudaijun/article/details/9273339
new 、operator new 和 placement new的更多相关文章
- 浅谈new operator、operator new和placement new 分类: C/C++ 2015-05-05 00:19 41人阅读 评论(0) 收藏
浅谈new operator.operator new和placement new C++中使用new来产生一个存在于heap(堆)上对象时,实际上是调用了operator new函数和placeme ...
- 浅析C++内存分配与释放操作过程——三种方式可以分配内存new operator, operator new,placement new
引言:C++中总共有三种方式可以分配内存,new operator, operator new,placement new. 一,new operator 这就是我们最常使用的 new 操作符.查看汇 ...
- 小结:c++中的new、operator new和placement new
小结:c++中的new.operator new和placement new new(也称作new operator),是new 操作符,不可重载 class T{...}; T *t = new T ...
- C++ 中 new 操作符内幕:new operator、operator new、placement new
一.new 操作符(new operator) 人们有时好像喜欢有益使C++语言的术语难以理解.比方说new操作符(new operator)和operator new的差别. 当你写这种代码: st ...
- C++中的new、operator new与placement new
转:http://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html new/delete与operator new/operator ...
- new表达式,operator new和placement new介绍
new/delete是c++中动态构造对象的表达式 ,一般情况下的new/delete都是指的new/delete表达式,这是一个操作符,和sizeof一样,不能改变其意义. new/delete表达 ...
- new、operator new、placement new
首先我们区分下几个容易混淆的关键词: new.operator new.placement new new和delete操作符我们应该都用过,它们是对堆中的内存进行申请和释放,而这两个都是不能被重载的 ...
- C++中的new,operator new与placement new
以下是C++中的new,operator new与placement new进行了详细的说明介绍,需要的朋友可以过来参考下 new operator/delete operator就是new和 ...
- C++ new operator, delete operator, operator new, operator delete, new placement
http://www.younfor.com/cpp-new-placement-new-operator-new.html http://www.cnblogs.com/luxiaoxun/arch ...
随机推荐
- GL_Oracle Erp常用的报表(汇总)
2014-06-27 BaoXinjian 1. 总账系统
- js复习(一)
一.常用数据框1.alert(""):警告对话框,作用是弹出一个警告对话框 2.confirm(""):确定对话框,弹出一个带确定和取消按钮的对话框--确定返回 ...
- RabbitMQ介绍3 - 运行和管理RabbitMQ
安装.官方介绍:http://www.rabbitmq.com/download.html.一般产品环境会部署到Linux环境,但做为简单尝试,可以部署到Windows上(这里是部署介绍:http:/ ...
- MODBUS-寄存器与功能码学习
分类 简称 起始地址 结束地址 能够使用的功能码 输出逻辑线圈/(可读写位)/(DI/O)(如继电器开关控制) 0x 00000 09999 0x01读一组逻辑线圈 0x05写单个线圈 0x0f写多个 ...
- Centos下yum配置lnmp环境
首先关闭SELINUX vi /etc/selinux/config #SELINUX=enforcing #注释掉 #SELINUXTYPE=tar ...
- 在linux下通过sh运行java程序
1.导出jar包放在目录下,如/home 2.通过vi创建sh文件如:test.sh,内容如:java -jar test1.jar com.wzh.test.test & 3.运行命令:sh ...
- 用R在字符串中提取匹配的部分
例如在aaaa12xxxx中提取12,在参考了stackoverflow后比较方便的大致有以下几种方法: 利用sub跟gsub sub(".*?([0-9]+).*", " ...
- jQuery 常见操作实现方式
一个优秀的 JavaScript 框架,一篇 jQuery 常用方法及函数的文章留存备忘. jQuery 常见操作实现方式 $("标签名") //取html元素 document. ...
- C++学习46 getline()函数读入一行字符 一些与输入有关的istream类成员函数
getline函数的作用是从输入流中读取一行字符,其用法与带3个参数的get函数类似.即 cin.getline(字符数组(或字符指针), 字符个数n, 终止标志字符) [例13.7] 用get ...
- 解决insmod: error inserting 'hello.ko': -1 Invalid module format
编译自己的内核模块后,insmod出现error:error inserting 'hello.ko': -1 Invalid module format 出现这种情况的原因是因为Makefile种使 ...