zoukankan      html  css  js  c++  java
  • [C++再学习系列] 深入new/delete:New的3种形态

    New3种形态: new operator、operator newplacement new

    new操作符 (new表达式 , new operator , new expression): 通常我们调用 X * pX = new X 时使用的就是这个操作符 , 由语言内建 , 不能重载 , 不能改变其行为 . 包括分配内存的 operator new 和调用构造函数的 placement new new关键字实际上做了三件事:获得一块内存空间、调用构造函数、返回正确的指针。当然,如果我们创建的是简单类型的变量,那么第二步会被省略。

    operator new : operator new 是一个函数 , void * operator new(size_t size) 。它分配指定大小的内存 , 可以被重载 , 可以添加额外的参数 , 但第一个参数必须为 size_toperator new 除了被 new operator 调用外也可以直接被调用 : void * rawMem = operator new(sizeof(X)) 。这种用法和调用 malloc 一样。

    placement new : placement new 在一块指定的内存上调用构造函数 , 包含头文件 <new> 之后也可以直接使用 placement new: X * pX = new (rawMem) X 

    new operator 类似 , 对于 delete operator, 也存在 operator delete: void operator delete(void *), 析构方法 pX->~X().

    New 的基本使用指南:

    想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果仅仅想分配内存,就应该调用operator new 函数;它不会调用构造函数。如果想定制在堆对象被建立时的内存分配过程,你应该写你自己的 operator new 函数,然后使用new操作符,new 操作符会调用定制的operator new 。如果想在一块已经获得指针的内存里建立一个对象,应该用 placement newplacement new 主要适用于:在对时间要求非常高的应用程序中,因为这些程序分配的时间是确定的;长时间运行而不被打断的程序;以及执行一个垃圾收集器 (garbage collector) 

    由于 placement new 的特殊性,下面给出其常规使用步骤:

    class Task ; //

    char * buff = new char[sizeof(Task)]; // 1) 分配内存

    Task *ptask = new(buff) Task ;        // 2) 构造对象

    ptask->suspend();      // 3) 正常使用对象

    ptask->resume();

    ptask->~Task();         // 4) 析构对象

    delete [] buff;             // 5) 释放内存

          显然, placement new 可以提高效率,但增加了程序的复杂度,需要自行管理对象的生存期。 Placement new 的使用大量存在于 STL

        New handler

        当new失败时,将抛出异常bad_alloc。如果想改变new失败处理流程,可定制自己的new-handler,并通过set_new_handler()来改变默认行为:

    例子1:

       typedef void (*PFV)(void);
    
       static char*  safety;
       static PFV    old_handler;
    
       void my_new_handler ()
       {
           delete[] safety;
           popup_window ("Dude, you are running low on heap memory.  You
    		      should, like, close some windows, or something.
    		      The next time you run out, we're gonna burn!");
           set_new_handler (old_handler);
           return;
       }
    
       int main ()
       {
           safety = new char[500000];
           old_handler = set_new_handler (&my_new_handler);
           ...
       }
    
    例子2:

    // #include <exception>
    #include <stdexcept>    // under /usr/include/c++/[G++ VERTION]/stdexcept
    
    using namespace std;
    
    static new_handler old_new_handler = 0;  // record old new handler
    
    void NewHandler()
    {
        /********* Release a lot of memory **********/
    
        if (old_new_handler)
            old_new_handler();
        else
            throw bad_alloc();
    }
    
    int main(int argc, char** argv)
    {
        old_new_handler = set_new_handler(&NewHandler);
        /* your progrom */
    
        return 0;
    }
    

    ---------------------------------------------------

    兄弟的公司:立即购--手机购物,诚信网购

    兄弟的公司:立即团

    欢迎转载,请注明作者和出处

  • 相关阅读:
    支付宝接口对接常见问题
    Myeclipse中配置安卓环境
    算法精解概述
    使用Eclipse开始Java编程
    Windows使用SSH管理Ubuntu
    大臣的旅费
    剪格子
    波动数列
    买不到的数目
    逆波兰表达式
  • 原文地址:https://www.cnblogs.com/zhenjing/p/3_kind_new.html
Copyright © 2011-2022 走看看