• 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

  • 相关阅读:
    内存可用性判断 IsBadCodePtr IsBadReadPtr 等等
    部署到Linux使用VS Code 开发.NET Core 应用程序
    Gulp.js简介
    net WebApi中使用swagger
    深入理解
    软件框架
    重拾linux
    Linux创建修改删除用户和组
    Linux 之 rsyslog
    Lua 解释器
  • 原文地址:https://www.cnblogs.com/yangtze736-2013-3-6/p/3667521.html
Copyright © 2020-2023  润新知