在指定的内存空间中构造对象,学习了一下new,原来还有这等东西!
看如下代码:
class MyClass {…};
MyClass * p=new MyClass;
这里的new实际上是执行如下3个过程:
1调用operator new分配内存;
2调用构造函数生成类对象;
3返回相应指针。
如果你想在已经分配的内存中创建一个对象,使用new是不行的。也就是说placement new允许你在一个已经分配好的内存中(栈或堆中)构造一个新的对象。原型中void*p实际上就是指向一个已经分配好的内存缓冲区的的首地址。我们知道使用new操作符分配内存需要在堆中查找足够大的剩余空间,这个操作速度是很慢的,而且有可能出现无法分配内存的异常(空间不够)。placement new就可以解决这个问题。我们构造对象都是在一个预先准备好了的内存缓冲区中进行,不需要查找内存,内存分配的时间是常数;而且不会出现在程序运行中途出现内存不足的异常。所以,placement new非常适合那些对时间要求比较高,长时间运行不希望被打断的应用程序。
使用方法如下:
1. 缓冲区提前分配
可以使用堆的空间,也可以使用栈的空间,所以分配方式有如下两种:
class MyClass {…};
char *buf=new char[N*sizeof(MyClass)+ sizeof(int) ] ; 或者char buf[N*sizeof(MyClass)+ sizeof(int) ];
2. 对象的构造
MyClass * pClass=new(buf) MyClass;
3. 对象的销毁
一旦这个对象使用完毕,你必须显式的调用类的析构函数进行销毁对象。但此时内存空间不会被释放,以便其他的对象的构造
pClass->~MyClass();
4. 内存的释放
如果缓冲区在堆中,那么调用delete[] buf;进行内存的释放;如果在栈中,那么在其作用域内有效,跳出作用域,内存自动释放
-----------------------------------------------------
贴一个别人的思考
-----------------------------------------------------
昨天用placement new初始化从内存池申请的一块内存。晚上回家路上突然想到,从内存池申请下来忘了检查是否成功了,直接就new(ptr)了。以为这样会出core。不过转念一想new怎么也会检查下指针是不是为NULL吧。所以今天早上写了一段代码做了个实验,实验证明,placement new是会判断ptr是否为NULL的。如果是NULL,直接返回。
#include <new> #include <iostream> class boo_t { public: boo_t(): _a(0), _b(0) { } private: int _a; int _b; }; int main(int argc, char *argv[]) { void *buf = (void *)0; boo_t *a = new(buf) boo_t(); std::cout<< "OK, get here and a is " << a << std::endl; return 0; }
- OK, get here and a is 0
#include <new> #include <iostream> class boo_t { public: boo_t(): _a(0), _b(0) { } private: int _a; int _b; }; int main(int argc, char *argv[]) { void *buf = (void *)1; boo_t *a = new(buf) boo_t(); std::cout<< "OK, get here and a is " << a << std::endl; return 0; }
文章来源:
http://blog.chinaunix.net/uid-23146151-id-3132996.html
http://hi.baidu.com/jakisou/item/2f663ff42ab4e219a62988fb