zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    POJ 2528 Mayor's posters 线段树+离散化
    Leveldb之version与version_set详细对比
    rocksdb编译测试的正确姿势
    ycsb使用方法
    memalign vs malloc
    四种监听器(自身类,外部类,内部类,匿名类)
    数据库基础
    哈希索引和Btree索引
    哈希表hashtable
    抽象类和接口
  • 原文地址:https://www.cnblogs.com/yangtze736-2013-3-6/p/3667521.html
Copyright © 2011-2022 走看看