重载new和deletehtml
首先借用C++ Primer 5e的一个例子:express
string *sp = new string("a value"); string *arr = new string[10];
new表达式调用一个名为operator new(或者operator new[])的标准函数,分配一块足够大的,原始的,未命名的内存空间来存储特定的类型或者对象的数组。
编译器运行相应的构造函数以构造这些对象,而且传入初值。
对象构造完毕后返回指向该对象的指针。
delete sp; delete[]arr;
对sp所指的对象或者arr所指的数组中的元素执行析构函数
而后第二部调用operator delete或者(operator delete[])的标准库来释放掉内存空间。
replaceable allocation functions void* operator new ( std::size_t count ); void* operator new[]( std::size_t count ); void* operator new ( std::size_t count, std::align_val_t al);(since C++17) void* operator new[]( std::size_t count, std::align_val_t al);(since C++17) replaceable non-throwing allocation functions(nothrow版本表示承诺不抛出异常,分配内存失败直接返回null,可是不保证构造函数不抛出异常,没什么使用必要) void* operator new ( std::size_t count, const std::nothrow_t& tag); void* operator new[]( std::size_t count, const std::nothrow_t& tag); void* operator new ( std::size_t count, std::align_val_t al, const std::nothrow_t&);(since C++17) void* operator new[]( std::size_t count, std::align_val_t al, const std::nothrow_t&);(since C++17) non-allocating placement allocation functions(注意这两个版本不能重定义, 也就是常见的placement new) void* operator new ( std::size_t count, void* ptr ); void* operator new[]( std::size_t count, void* ptr ); user-defined placement allocation functions void* operator new ( std::size_t count, user-defined-args... ); void* operator new[]( std::size_t count, user-defined-args... ); void* operator new ( std::size_t count, std::align_val_t al, user-defined-args... ); (since C++17) void* operator new[]( std::size_t count, std::align_val_t al, user-defined-args... );(since C++17) class-specific allocation functions void* T::operator new ( std::size_t count ); void* T::operator new[]( std::size_t count ); void* T::operator new ( std::size_t count, std::align_val_t al );(since C++17) void* T::operator new[]( std::size_t count, std::align_val_t al );(since C++17) class-specific placement allocation functions void* T::operator new ( std::size_t count, user-defined-args... ); void* T::operator new[]( std::size_t count, user-defined-args... ); void* T::operator new ( std::size_t count, std::align_val_t al, user-defined-args... );(since C++17) void* T::operator new[]( std::size_t count, std::align_val_t al, user-defined-args... );(since C++17)
replaceable usual deallocation functions void operator delete ( void* ptr ); void operator delete[]( void* ptr ); void operator delete ( void* ptr, std::align_val_t al );(since C++17) void operator delete[]( void* ptr, std::align_val_t al );(since C++17) void operator delete ( void* ptr, std::size_t sz );(since C++14) void operator delete[]( void* ptr, std::size_t sz );(since C++14) void operator delete ( void* ptr, std::size_t sz, std::align_val_t al );(since C++17) void operator delete[]( void* ptr, std::size_t sz, std::align_val_t al );(since C++17)
replaceable placement deallocation functions(同new,只能保证operator delete不抛出异常,可是不能保证析构不抛出异常) void operator delete ( void* ptr, const std::nothrow_t& tag ); void operator delete[]( void* ptr, const std::nothrow_t& tag ); void operator delete ( void* ptr, std::align_val_t al, const std::nothrow_t& tag );(since C++17) void operator delete[]( void* ptr, std::align_val_t al, const std::nothrow_t& tag );(since C++17)
non-allocating placement deallocation functions(也就是传统意义上的placement delete) void operator delete ( void* ptr, void* place ); void operator delete[]( void* ptr, void* place );
user-defined placement deallocation functions void operator delete ( void* ptr, args... ); void operator delete[]( void* ptr, args... );
class-specific usual deallocation functions void T::operator delete ( void* ptr ); void T::operator delete[]( void* ptr ); void T::operator delete ( void* ptr, std::align_val_t al );(since C++17) void T::operator delete[]( void* ptr, std::align_val_t al );(since C++17) void T::operator delete ( void* ptr, std::size_t sz ); void T::operator delete[]( void* ptr, std::size_t sz ); void T::operator delete ( void* ptr, std::size_t sz, std::align_val_t al );(since C++17) void T::operator delete[]( void* ptr, std::size_t sz, std::align_val_t al );(since C++17)
class-specific placement deallocation functions void T::operator delete ( void* ptr, args... ); void T::operator delete[]( void* ptr, args... );
non-allocating placement allocation functions(注意这两个版本不能重定义, 也就是常见的placement new) void* operator new ( std::size_t count, void* ptr ); void* operator new[]( std::size_t count, void* ptr ); non-allocating placement deallocation functions(也就是传统意义上的placement delete) void operator delete ( void* ptr, void* place ); void operator delete[]( void* ptr, void* place );
new (place_address) type new (place_address) type (initializers) new (place_address) type [size] new (place_address) type [size]{ braced initializer list }
template <class _T1> inline void _Construct(_T1* __p) { new ((void*) __p) _T1(); } template <class _Tp> inline void _Destroy(_Tp* __pointer) { __pointer->~_Tp(); }
class Widget { public: Widget(int i) :m_haha(i) { throw std::exception(); } static void *operator new(std::size_t size, std::ostream& logStream); static void operator delete(void *pMemory) { ::operator delete(pMemory); } static void operator delete(void *pMemory, std::ostream& logStream); private: int m_haha; }; void *Widget::operator new(std::size_t size, std::ostream& logStream) { cout << "Hello World" << std::endl; while (true) { auto p = malloc(size); if (p) return p; auto h = get_new_handler(); if (!h) h(); else
throw std::bad_alloc(); } } void Widget::operator delete(void *pMemory, std::ostream& logStream) { cout << "Hello World delete" << std::endl; ::delete pMemory; } int main() { try { Widget *k = new (std::cout) Widget(1); delete k; } catch (const std::exception&) { } return 0; }
class DerivedWidget : public Widget { public: using Widget::operator delete; using Widget::operator new; static void *operator new(std::size_t size, const std::nothrow_t nt); static void operator delete(void *pMemory, const std::nothrow_t nt); };
typedef void (__CLRCALL_PURE_OR_CDECL * new_handler) (); #endif /* !defined(_INC_NEW) || !defined(_MSC_EXTENSIONS) */
// FUNCTION AND OBJECT DECLARATIONS
_CRTIMP2 new_handler __cdecl set_new_handler(_In_opt_ new_handler) _THROW0(); // establish alternate new handler
_CRTIMP2 new_handler __cdecl get_new_handler() _THROW0(); // get current new handler
_STD_END
让更多内存可被使用
安装另外一个new-handler(若是当前的new-handler没法获取更多的内存,能够用另外一个代替)
卸载new-handler
抛出bad_alloc(或者派生自此异常的其余异常),让异常传播到其余地方
不返回,调用abort或者exit
template<typename T>
class NewHandlerSupport { public: NewHandlerSupport() = default; explicit NewHandlerSupport(std::new_handler h):_handler(h) { } ~NewHandlerSupport() { std::set_new_handler(_handler); } static void *operator new(std::size_t size) { ::operator new(size); } static void *operator new(std::size_t size, std::ostream& logStream); static void operator delete(void *pMemory) { ::operator delete(pMemory); } static void operator delete(void *pMemory, std::ostream& logStream); static std::new_handler set_new_handler(std::new_handler p)noexcept; private: std::new_handler _handler;//拿来临时替换的
static std::new_handler _currnentHandler; NewHandlerSupport(NewHandlerSupport &&) = default; NewHandlerSupport(const NewHandlerSupport &) = delete; NewHandlerSupport& operator=(const NewHandlerSupport &) = delete; }; template<typename T> std::new_handler NewHandlerSupport<T>::set_new_handler(std::new_handler p)noexcept { std::new_handler oldHandler = _currnentHandler; _currnentHandler = p; return oldHandler; } template<typename T>
void NewHandlerSupport<T>::operator delete(void *pMemory, std::ostream& logStream) { cout << "Hello World delete" << std::endl; ::delete pMemory; } template<typename T>
void * NewHandlerSupport<T>::operator new(std::size_t size, std::ostream& logStream) { NewHandlerSupport h(std::set_new_handler(_currnentHandler)); cout << "Hello World" << std::endl; return ::operator new(size); } template<typename T>std::new_handler NewHandlerSupport<T>::_currnentHandler = 0; class Widget : public NewHandlerSupport<Widget> { public: Widget(int i) :m_haha(i) { } private: int m_haha; };
Widget::set_new_handler(error); Widget *k = new (std::cout) Widget(1); delete k;
void* __CRTDECL operator new(size_t const size) { 00007FF74DC58630 mov qword ptr [rsp+8],rcx 00007FF74DC58635 sub rsp,38h for (;;) { if (void* const block = malloc(size)) 00007FF74DC58639 mov rcx,qword ptr [size] 00007FF74DC5863E call malloc (07FF74DC513FCh) 00007FF74DC58643 mov qword ptr [rsp+20h],rax 00007FF74DC58648 cmp qword ptr [rsp+20h],0 00007FF74DC5864E je operator new+27h (07FF74DC58657h) { return block; 00007FF74DC58650 mov rax,qword ptr [rsp+20h] 00007FF74DC58655 jmp operator new+4Bh (07FF74DC5867Bh) } if (_callnewh(size) == 0) 00007FF74DC58657 mov rcx,qword ptr [size] 00007FF74DC5865C call _callnewh (07FF74DC516B8h) 00007FF74DC58661 test eax,eax 00007FF74DC58663 jne operator new+49h (07FF74DC58679h) { if (size == SIZE_MAX) 00007FF74DC58665 cmp qword ptr [size],0FFFFFFFFFFFFFFFFh 00007FF74DC5866B jne operator new+44h (07FF74DC58674h) { __scrt_throw_std_bad_array_new_length(); 00007FF74DC5866D call __scrt_throw_std_bad_array_new_length (07FF74DC51604h) } else 00007FF74DC58672 jmp operator new+49h (07FF74DC58679h) { __scrt_throw_std_bad_alloc(); 00007FF74DC58674 call __scrt_throw_std_bad_alloc (07FF74DC5120Dh) } } // The new handler was successful; try to allocate again...
} 00007FF74DC58679 jmp operator new+9h (07FF74DC58639h) }
void __CRTDECL operator delete(void* const block) noexcept { 00007FF74DC586A0 mov qword ptr [rsp+8],rcx 00007FF74DC586A5 sub rsp,28h #ifdef _DEBUG _free_dbg(block, _UNKNOWN_BLOCK); 00007FF74DC586A9 mov edx,0FFFFFFFFh 00007FF74DC586AE mov rcx,qword ptr [block] 00007FF74DC586B3 call _free_dbg (07FF74DC5119Ah) #else
free(block); #endif }
std::allocator<string> alloc; auto p = alloc.allocate(10); alloc.construct(p, "fuck");