IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++-内存 -> 正文阅读

[C++知识库]C++-内存

作者:recommend-item-box type_blog clearfix

标准类型字节

类型 字节
byte 1
bool 1
char 1
short 2
long 4
int 4
double 8
long long 8
指针 32位4 64位8

new

int *a = new int;
运算符 他是没办法改变的 他一定执行两件事情 一个是调用构造函数 一个是给指针分配内存 也就是调用operator new函数
他做了什么事情

/*A *a = new A*/
void *p = A::operator new(sizeof(A));
A* a1 = static_cast<A*>(p);
a1->A::A();
return a1;

operator new函数 我们是可以重载的

class Node
{
    
public:
/*在这里我们重载operator new函数*/
    void* operator new(size_t t) { cout << "调用了operator new函数"<<endl; 
    void * temp = malloc(t);
    return temp; };
    int a;//4
    char b;//1
    Node() :a(1), b('b')
    {
        cout << "调用了构造函数"<<endl;
    }
};
int main()
{
    Node* node = new Node();
}

请添加图片描述

void * operator new(size)

是函数 不是运算符 返回的是一个void*
分为全局重载和类重载 系统默认的全局重载就只是调用了malloc
A* a = new A;我们知道这里分为两步:1.分配内存,2.调用A()构造对象。事实上,分配内存这一操作就是由operator new(size_t)来完成的,如果类A重载了operator new,那么将调用A::operator new(size_t ),如果没有重载,就调用::operator new(size_t )
::operator new(size_t )是全局的

系统中真正的内存分配

请添加图片描述
系统中并不是你要分配多少内存就在系统中占用多少内存
如图
block size那块蓝色的区域是真实分配的大小 上面和下面都有填充0xfdfdfdfd用来分割客户可以使用的内存区和不可使用的内存区 同时,当这块内存被归还时,编辑器也可以通过下gap的值区判断当前内存块是否被越界使用了。 这也是为什么只能分配比用户申请更大的内存给用户 也就是用户申请10字节的 你必须给12字节的(为了对齐) 原因在于你如果给8字节的 虽然我们总的分配的内存更大 因为有cookie啊 或者debug什么的 但是 如果你少给了 例如申请10字节 你给8字节 那么多的两个字节数据就被写在了0xfdfdfdfd这里的前两个fd被覆盖了 那么系统检测到只有两个fd就会直接崩溃

最上面和最下面都有一个cookie占4个字节 这个cookie会记录这块内存总共用了多少 这cookie作用是在释放的时候知道要释放到哪个Header链表末尾去(Header应该就是一个内存池)
debug header那块区域是调试信息存储的地方 这也是debug版本的程序为什么会比release版本大很多的原因
并且总大小要为16的倍数

小内存分配(内存池)

就会用上内存池 主要也是为了减少cookie等空间白白消耗
在进入程序之前 系统就会分配一个堆空间 这个堆空间用于管理的动态分配 他会创建一个长度为16的类型为HEADER的链表 这个链表的每一个结点都会管理一个1MB的空间 我的感觉就是 如果这个空间被申请出去了 那么就为1 没有就为0
free和delete不需要提供大小参数的原因在于他只需要将这个链表相应结点置为1就行了 不需要知道要释放多大内存 释放的时候通过cookie就知道释放的这个内存是多大 要放到哪个header链表中去
请添加图片描述

请添加图片描述
这个就是Header链表的样子 16下面挂着的就是 最开始如果16下面没有挂着内存块 系统就会分配一块很大的内存然后分割成很多个16字节的内存块挂在16下面 如果有人要申请8-16字节的内存 就从这拿

内存池同样会产生碎片

主要原因是 例如如果我们在8字节的内存块都用完而16字节的内存块还有的时候 我们再申请8字节内存 并不会找系统要一块很大的内存再重新分割 而是找一个最适合他的 例如16字节的 分割8字节给用户 然后剩下8字节就重新挂到8字节下面 不能挂回16字节下面 如果挂回去 下次要申请16字节的时候 就会出问题 那么时间长了 就会小的字节链表下面挂了很多被分割的内存块 然后大的字节链表字节块都被分割了 但是实际上用户又把这些内存块归还了
请添加图片描述
像这样

具体看这篇博客

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 23:03:14  更:2021-08-10 23:03:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 18:16:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码