placement new

在指定的内存空间中构造对象,学习了一下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;
}

 

如果placement new不做检测的话,那么就会出core,结果程序正常运行,输出结果:
  1. 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;
}
 
只是将buf换为了1,但是同样是非法内存,这个破坏了NULL的检测,所以结果就是core dump。
通过以上就是想说,placement new简单的NULL检测还是有的,所以内存申请失败不要紧,放心大胆的用吧。new之后再检测也不晚。

 

文章来源:

http://blog.chinaunix.net/uid-23146151-id-3132996.html

http://hi.baidu.com/jakisou/item/2f663ff42ab4e219a62988fb

posted @ 2014-04-15 22:31  艾丽娅的猫  阅读(203)  评论(0编辑  收藏  举报