new

new 和 delete 的执行过程

new 的执行过程

  • 通过 operator new 申请内存

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

  • 返回内存指针

delete 的执行过程

  • 调用析构函数(简单类型忽略此步)
  • 释放内存
using namespace std;
class T
{
public:
	T()
	{
		cout << "constructor\n";
	}

	~T()
	{
		cout << "deconstructor\n";
	}

	void * operator new(size_t sz)
	{
		T* t = (T*)malloc(sizeof(T));
		cout << "malloc memory\n";
		return t;
	}

	void operator delete(void* p)
	{
		free(p);
		cout << "free memory\n";
	}
};


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  
上一篇:C++内存


下一篇:c语言存储管理