美文网首页
2020-10-11

2020-10-11

作者: 虞培峰yannis | 来源:发表于2020-10-11 21:05 被阅读0次

总览

C++内存管理是一个比较重要的一个话题,一个好的内存管理可以增加程序的鲁棒性,提高运行效率以及合理有效的利用有限的内存空间。本博客是根据侯捷老师在Boolan上面的课《C++内存管理》整理的,中间也会穿插一些其他方面的内存管理内容。

相关资源

1、课程:侯捷老师的《C++内存管理》https://www.bilibili.com/video/av24603588/?spm_id_from=333.788.videocard.0

2、博客:Dougle写的malloc:http://g.oswego.edu/

3、书籍:《STL源码剖析》 和《深入理解计算机系统》

内存分配的每一个层面

image

<center>C++内存管理的4个层面</center>

如上图所示,在C++中内存管理的层次有4层,分别是:

1、 C++标准库提供的std::allocator这个分配器。

2、 C++的原生构件,比如new、new[ ]、::operator new等等。

3、 C标准库函数malloc和free。

4、 操作系统分配内存的函数,这个和操作系统有关,我们一般不会去操作。

一般对于一个C++应用来说,其内存管理都是分层调用的。比如我们使用C++标准库中的容器,容器中会调用std::allocator这个分配器,而目前一般的分配器会调用::operator new和::operator delete这些C++内存分配的构件,那如果我们要深挖源代码的话,::operator new和::operator delete会调用malloc和free函数,那么malloc和free这些函数继续还是会调用操作系统的函数。在后面会将这一层层的调用关系给讲解明白,下表是这四层函数的简介归纳。

<center>C++基本内存函数归纳</center>

内存分配函数 内存释放函数 类别 可否重载
malloc() free() C函数 不可
new delete C++表达式 不可
::operator new() ::operator delete() C++函数
allocator<T>::allocate() allocator<T>::deallocate() C++标准库 可自由搭配容器

四种内存管理函数使用

以下是四种内存管理函数的使用方法:

<center>四种内存管理函数使用方法</center>

#include <iostream>
#include <cstdlib>
#include <complex>
#include <ext/pool_allocator.h>
#include "../include/test.h"
using namespace std;

int test1(){
    void *p1 = malloc(512);
    free(p1);

    complex<int>* p2 = new complex<int>;
    delete p2;

    void* p3 = ::operator new(512);
    ::operator delete(p3);

#ifdef __GNUC__
    int* p4 = allocator<int>().allocate(3, (int*)0);    //使用allocator分配,需要指定分配对象的类型和个数
    allocator<int>().deallocate(p4, 3);         //在回收内存的时候需要指定回收的指针和回收的相应的个数,这个比较烦人
    cout << __GNUC__ << endl;
    cout << "正在使用GNU的分配器" << endl;
    
    //正在使用__gnu_cxx命名空间下的__pool_alloc分配器,这个分配器质量比较好
    void* p5 = __gnu_cxx::__pool_alloc<int>().allocate(9);
    __gnu_cxx::__pool_alloc<int>().deallocate(static_cast<int*>(p5), 9);
#endif
    return 0;
}

在上表中比较有意思的是标准库自带的allocator分配器在回收内存空间的时候需要传入指针和相对应的元素个数,比如例子中回收内存的时候要把3个int给传入进去。(如果这里的allocator和deallocator只是简单的包装new和delete这两个函数的话,那deallocate函数传入的个数就没啥意义,实际上应该是用不到的。但是如果我们的allocator考虑了内存池的设计,那么deallocate实际上并不是回收内存,而是在某些地址上调用相应的析构函数来将若干个对象析构掉,这样这个传入的表示个数的实参就有用处了,后面具体要看C++内存池的设计原理),这个是其他构件所没有的。我们看allocator的第二种用法,这里我们使用了__gnu_cxx(一些比较好的std的扩展)命名空间下__pool_alloc这个分配器,那__pool_alloc分配器和std::allocator这两个分配器有啥区别呢std::allocator分配器只是对new和delete这两个函数进行了简单的包装,但是__pool_alloc这个分配器则是采用了内存池的技术,更加好一点。那么STL为什么不用更好的__pool_alloc这个分配器呢,或许是现在计算机的内存比较多吧(😄)。

相关文章

  • Git 全局设置技巧-转换换行符问题

    2020-10-11 Git 全局设置技巧1、提交检出均不转换换行符 git config --global co...

  • 鉴峰丨秋意

    [连续签到第1007天] 2020-10-11 周日快乐 岁月匆忙, 此岸花落, 彼岸花开。 唯愿, 花开花落, ...

  • 2020-10-11 思考成长周复盘

    一 时间 2020-10-05 ~ 2020-10-11 二 围绕思考成长所做的事情 1.每日早起。2 发现被书商...

  • 2020-10-26

    2020-10-11 清月镜湖两不同,亭台楼阁碧联盈。 孤身望尽天涯路,意欲结心相伴行。

  • 【佛系定投训练营】第4课作业

    【佛系定投训练营】第4课作业 2020-10-08 20:00至2020-10-11 00:00 作业4.1:找到...

  • 2020年10月11日西点笔记-慕斯蛋糕/玛芬蛋糕

    公元2020-10-11日 星期日 慕斯蛋糕 配方: 牛奶100克,蛋黄两个,巧克力150克,动物淡奶油250克,...

  • 2020-10-11

    【2020-10-11 农历八月二十五 星期日 晴 日 更242天】 很冷。 今天我和少年都休息,但是我们...

  • 随笔小诗

    工作到累心门堵, 起身捉来一抹绿, 细端慢品生惬意, 重振神彩又学习。 笔悠悠2020-10-11

  • 【周总结】第十期第4周07号-醒

    2020-10-11 【本周计划/总结】 一、职业 猛然发现自己的总结有点碎碎念的感觉,怎么才能像别人一样,既有总...

  • 2020-10-11

    中原焦点团队祝澜 1019天 2020-10-11 本周约练第3次(咨) 共224次 今早5:40,和两位老...

网友评论

      本文标题:2020-10-11

      本文链接:https://www.haomeiwen.com/subject/pqcypktx.html