zoukankan      html  css  js  c++  java
  • new

    new 和 delete 的执行过程

    new 的执行过程

    • 通过 operator new 申请内存

    • 调用构造函数(简单类型忽略此步)

    • 返回内存指针

    delete 的执行过程

    • 调用析构函数(简单类型忽略此步)
    • 释放内存
    using namespace std;
    class T
    {
    public:
    	T()
    	{
    		cout << "constructor
    ";
    	}
    
    	~T()
    	{
    		cout << "deconstructor
    ";
    	}
    
    	void * operator new(size_t sz)
    	{
    		T* t = (T*)malloc(sizeof(T));
    		cout << "malloc memory
    ";
    		return t;
    	}
    
    	void operator delete(void* p)
    	{
    		free(p);
    		cout << "free memory
    ";
    	}
    };
    
    
    int main()
    {
    	T* t = new T{};
    	delete t;
    	
    	return 0;
    }
    

    输出:

    malloc memory
    constructor
    deconstructor
    free memory
    

    new/delete 和 delete/malloc 的比较

    new 和 malloc 的比较

    • new 失败时会调用 new_handler 处理函数,malloc 不会,失败时返回 NULL
    • new 能自动调用对象的构造函数,malloc 不会
    • new出来的东西是带类型的,malloc 是 void*,需要强制转换
    • new 是 C++ 运算符,malloc 是 C 标准库函数

    delete 和 free 的比较

    • delete 能自动调用对象的析构函数,malloc 不会
    • delete 是 C++ 运算符,free 是 C 标准库函数

    new 的三种形态

    new 的三种形态:

    • new operator
    • operator new
    • placement new

    new operator

    上面所说的 new 就是 new operator,共有三个步骤组成(申请内存,调用构造函数,返回内存指针)。

    • 是 C++ 的操作符。
    • 不可以被重载。

    operator new

    只分配所要求的空间,不调用相关对象的构造函数。当无法满足所要求分配的空间时,则如果有 new_handler,则调用 new_handler,否则如果没要求不抛出异常(以 nothrow 参数表达),则执行 bad_alloc 异常,否则返回 0。

    • 是 C++ 库函数。
    • 可以被重载
      • 重载时,返回类型必须声明为 void*。
      • 重载时,第一个参数类型必须为表达要求分配空间的大小(字节),类型为 size_t。
      • 重载时,可以带其它参数。如果重载了 operator new,那么也得重载对应的 operator delete。
      • 如果类中没有重载 operator new,那么调用的就是全局的 ::operator new 来完成堆的分配。

    placement new

    placement new 是重载operator new 的一个标准、全局的版本,它不能够被自定义的版本代替。

    声明在头文件 <new> 中,如果想在一块已经获得的内存里建立一个对象,那就应该用 placement new。

    placement new 适用于:在对时间要求非常高的应用程序中,因为这些程序分配的时间是确定的;长时间运行而不被打断的程序;以及执行一个垃圾收集器。

    Placement new 使用步骤

    • 缓存提前分配,有三种方式:
      • 在堆上进行分配:char * buff = new [sizeof(Task)];
      • 在栈上进行分配:char buf[N*sizeof(Task)];
      • 直接通过地址来使用,(必须是有意义的地址):void* buf = reinterpret_cast<void*> (0xF00F);
    • 对象的分配,在刚才已分配的缓存区调用placement new来构造一个对象:Task *ptask = new (buf) Task
    • 使用,按照普通方式使用分配的对象:ptask->memberfunction();.
    • 对象的析构,一旦你使用完这个对象,你必须调用它的析构函数来毁灭它。按照下面的方式调用析构函数:ptask->~Task();
    • 释放,可以反复利用缓存并给它分配一个新的对象,如果不打算再次使用这个缓存,你可以象这样释放它:delete [] buf;
     char* ptr = new char[sizeof(T)]; //@ allocate memory  
     T* tptr = new(ptr) T;            //@ construct in allocated storage ("place")  
     tptr->~T();                      //@ destruct  
     delete[] ptr;                    //@ deallocate memory  
    
  • 相关阅读:
    Hibernate之二级缓存
    Hibernate之HQL
    Hibernate 一对多自关联 多对多
    hibernate关联关系(一对多)
    Hibernate之主键生成策略
    Hibernate01
    struts的图片上传
    HashMap和HashTable本质性的区别
    集合03
    集合
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/14756784.html
Copyright © 2011-2022 走看看