C++ 内存管理之operator new
C++提供了new和delete方式来申请和释放堆区内存,但new和delete是指的expression,而底层是operator new函数。下面来区分一下这几个概念。
-
new/delete expression
new expression动态分配内存,delete expression释放内存。网上也有说是new operator的,这种说法属实容易让人误解...😅
-
new expression的行为分析
-
通过调用合适的内存分配函数,也就是
operator new()
-
void指针转型和初始化对象,类似于
A* p = static_cast<A*>(::operator new(size))p->A();
但是用户不能直接这样调用,只能用placement new,即
new(static_cast<A*>p) A()
A* p = new A; // allocates memory by calling: operator new (sizeof(A)) // and then constructs an object at the newly allocated space
-
-
delete expression的行为分析
- 调用析构
- 释放内存
-
placement new
在已分配的内存空间上,初始化对象(调用构造函数)
如果给new-expression提供了placement-params(指针),这个参数会作为placement new版本的
operator new
的额外参数,具体为void* operator new(std::size_t, void*)
,这个函数只是返回第二个参数。注意这种方式,需要手动调析构函数,否则可能会内存泄露
// within any block scope... { alignas(T) unsigned char buf[sizeof(T)]; // Statically allocate the storage with automatic storage duration // which is large enough for any object of type `T`. T* tptr = new(buf) T; // Construct a `T` object, placing it directly into your // pre-allocated storage at memory address `buf`. tptr->~T(); // You must **manually** call the object's destructor // if its side effects is depended by the program. } // Leaving this block scope automatically deallocates `buf`.
-
-
operator new
allocation functions,<new>中给出了三个版本
throwing (1) void* operator new (std::size_t size); nothrow (2) void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) noexcept; placement (3) void* operator new (std::size_t size, void* ptr) noexcept;
第一个版本,分配size字节的空间,失败
throw std::bad_alloc
第二个版本,分配size字节的空间,不抛出异常,
return null
第三个版本,直接返回
ptr
,当使用new-expression调用此版本时,是placement new