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

__EOF__

本文作者刘皇叔
本文链接https://www.cnblogs.com/xiaojianliu/p/14756784.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   刘-皇叔  阅读(165)  评论(0编辑  收藏  举报
编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
点击右上角即可分享
微信分享提示