当前位置: 首页> 教育> 培训 > 企业建设网站公司_seo排名工具快速提高_如何做电商新手入门_如何创建自己的卡网

企业建设网站公司_seo排名工具快速提高_如何做电商新手入门_如何创建自己的卡网

时间:2025/8/2 21:52:49来源:https://blog.csdn.net/m0_74795952/article/details/143168526 浏览次数:0次
企业建设网站公司_seo排名工具快速提高_如何做电商新手入门_如何创建自己的卡网

侯捷 | C++ | 内存管理 | 学习笔记(一)

第一章节 primitives

重点:技术的演进

new delete针对一个对象->static alloctor针对一个类->globa allocator针对一个标准库,里面有16个链表(static alloctor只有一个链表)

本部分介绍到static alloctor

文章目录

  • 侯捷 | C++ | 内存管理 | 学习笔记(一)
  • 第一章节 primitives
    • 一、new()和delete()
      • 1. new()
      • 2.delete()
      • 3.new[ ]和delete[ ]
      • 4.placement new
    • 二、重载
      • 1.new()和delete()
      • 2.allocator()和deallocator()
      • 3.new_handler

在C++内存分配当中分为四个阶层:

1.调用容器
  2.使用new关键词
  3.直接调用malloc和free
  4.调用与系统绑定的内存分配函数

这四个阶层有层层包含的关系:
在这里插入图片描述
从::operateor new()开始,可以进行重载。同理,delete也可以进行重载。

new会调用operator new,然后operator new调用malloc进行内存分配

在第四个,你可以自己设计一个分配器搭配一个容器。

在这里插入图片描述

一、new()和delete()

1. new()

在这里插入图片描述
new关键词相当于进行两个步骤

1.调用operator new,分配所创建对象需要的内存(其内部就是对malloc()的封装)
  2.调用对象的构造函数

如果某个步骤发生错误,则抛出异常。

注意:在一些版本中,只有编译器可以直接调用构造函数,如果在程序中自己调用则会出错。

A* pA = new A(1);//正确pA->A::A(3);//错误A::A(5);//错误

2.delete()

在这里插入图片描述
相应的,delete关键词也相当于两个步骤:

1.先对需要delete的对象进行析构,调用其析构函数
  2.再释放该对象所使用的内存空间(内部是封装了free()函数)

3.new[ ]和delete[ ]

在这里插入图片描述
  使用new[ ]时,顺序分配对象所需空间,指针指向第一个内存空间,但不调用构造函数进行初始化(如果对象内不包含指针成员则无影响,包含则有影响),后续可以通过指针对各个对象进行初始化。同时在空间开头会有一个cookie,记录了这个空间共有几个对象。
  使用delete[ ]时会读取cookie,倒序析构对象,并释放对应的空间;如果直接使用delete则不会读取cookie,会导致空间错位,程序报错,所以new[ ]必须要跟delet[]对应
在这里插入图片描述

4.placement new

在这里插入图片描述
  形式就相当于new ( p ) ,是将一块已经分配好了的内存用于构建对象,new则是当场分配一块内存用于构建对象,并没有特定的placement delete

其中buf是已经分配好的内存

上面第二行这一行会被编译器解释为这三行

image-20241022174140625

1.给一块已经分配好的内存,这一步其实什么都不会做,因为内存已经分配好了

2.转型

3.调用对象的构造函数

其实就相当于调用了一次构造函数

二、重载

1.new()和delete()

new()表达式本身不可重载,表示operator new(),但operator new()可以重载,分为全局和类内,通常重载类内的。
在这里插入图片描述
  类内对operator new()和operator delete()进行重载,operator new()重载的第一参数必须是size_t,其大小足以保证存储内存中对象的大小,否则将抛出异常。
在这里插入图片描述
  如果在创建对象时,直接调用new()和delete(),则调用的是类内重载的new()和delete(),是编译器调用的,并且重载的new和delete这两个函数一定得是静态的,因为调用的时候还没有实例对象
在这里插入图片描述
  如果调用::new()和::delete(),则调用的是全局的new()和delete()
在这里插入图片描述
  注意:

这里说的是placement operator delete不是operator delete

前者是下图说的抛异常的时候用,后者是和operator new配对的

在这里插入图片描述

很好的例子:

这是我们平常用的string,它的new会多出来一个extra,所以要重载

image-20241022201812108

2.allocator()和deallocator()

进行类内operator new()和operator delete()的重载,主要是为了减少::operator new()和::operator delete()的调用。因为::operator new()是对malloc()适配,每调用一次malloc(),就会产生头尾两个cookie共8个字节,既造成了空间浪费,速度上也更慢。

但对每一个不同的类进行重载,并且每次重载的内容都差不多,会造成大量重复劳动,会有很多的重复代码,所以设计一个概念把之前重载中共同的部分抽象出来,作为一个类来使用,即为allocator()和deallocator()。

设计一个allocator的类,在类里面定义allocator()和deallocator()。allocator()使用内存池模式,每次申请一大块内存,然后将这块内存切割小块,大小等同于对象的大小,并串成一个链表。这样只有在申请一大块内存的时候会调用malloc(),生成两个cookie,创建对象时不使用malloc(),而是从链表中取出一块分给对象,调用deallocator()也不将释放的内存free()给系统,而且将这块内存重新插入链表顶端。

重载operator new和delete的版本

image-20241022202556920

测试结果会有cookie的空间占用

现在这样就不需要上面又是struct又是union的

在这里插入图片描述

static allocator(用allocator的版本)

对象需要重载new和delete时,直接在类内创建一个allocator对象,调用allocator的类方法,即上面那张图。

使用static使得每个类有一个自己的内存池,进行内存管理,而不是一个对象一个内存池

测试结果没有cookie的空间占用

在这里插入图片描述

application class的所有内存分配的细节都让allocator去操心,我们的工作是让application class正常工作

使用宏把重复的代码定义一下来使用的版本

image-20241022205628521

测试结果没有cookie的空间占用,和static版本相同

技术的演进

new delete针对一个对象->static alloctor针对一个类->globa allocator针对一个标准库,里面有16个链表(static alloctor只有一个链表)

3.new_handler

在调用内存失败,抛出异常之前,会调用一个由自己设计的一个补救函数,即new_handler()。若new_handler()中没有abort()或者exit(),或者没有让更多内存可用,则会一直调用new_handler()直至满足内存需求。
image-20241022210612589

//调用:
//在main中写
set_new_handler(自己写的补救函数名);

注:

new delete的重载不可以是=default的,但可以是=delete的

关键字:企业建设网站公司_seo排名工具快速提高_如何做电商新手入门_如何创建自己的卡网

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: