《STL源码剖析》笔记——allocator

news2025/5/14 2:55:49

六大组件间关系

在这里插入图片描述

部分STL文件包含关系

在这里插入图片描述
allocator包含于中:
实际实现于三个文件 :
1.stl_construct.h :对象的构造和析构
2.stl_alloc.h空间配置和释放
3.stl_uninitialized.h

空间配置器(allocator)

1.什么是空间配置器?
为容器取得数据存储空间的类template从用户代码std::vector v;开始,vector的模板参数class T被替换为int,同时第二个模板参数因为没有指定,所以为默认模板参数,即allocator,这个vector对象v会在内部实例一个allocator的对象,用来管理内存。

2.空间配置器需要哪些功能?
负责空间配置与管理,从实现了动态空间配置、空间管理、空间释放的class template

空间配置器(allocator)标准接口

//traits 编程技法可以暂时不了解
allocator::value_type
allocator::pointer
allocator::const_pointer
allocator::reference
allocator::const_reference
allocator::size_type
allocator::difference

// 一个嵌套的(nested)class template,class rebind<U>拥有唯一成员other,那是一个typedef,代表allocator<U>
allocator::rebind

allocator::allocator() // 默认构造函数
allocator::allocator(const allocator&) // 拷贝构造函数
template <class U>allocator::allocator(const allocator<U>&) // 泛化的拷贝构造函数
allocator::~allocator() // 析构函数

// 返回某个对象的地址,a.address(x)等同于&x
pointer allocator::address(reference x) const
// 返回某个const对象的地址,a.address(x)等同于&x
const_pointer allocator::address(const_reference x) const

// 配置空间,足以存储n个T对象。第二个参数是个提示。实现上可能会利用它来增进区域性(locality),或完全忽略之
pointer allocator::allocate(size_type n, const void* = 0)
// 释放先前配置的空间
void allocator::deallocate(pointer p, size_type n)

// 返回可成功配置的最大量
size_type allocator:maxsize() const

// 调用对象的构造函数,等同于 new((void*)p) T(x)
void allocator::construct(pointer p, const T& x)
// 调用对象的析构函数,等同于 p->~T()
void allocator::destroy(pointer p)

一个最简单的allocator就可以理解为对new,delete的简单封装,以及对构造函数和析构函数的直接调用。

书中实现

#ifndef _MYALLOC_
#define _MYALLOC_

#include <new>
#include <cstddef>
#include <cstdlib>
#include <climits>
#include <iostream>

namespace my_alloc
{
    // allocate的实际实现,简单封装new,当无法获得内存时,报错并退出
    template <class T>
    inline T* _allocate(ptrdiff_t size, T*) {
        set_new_handler(0);
        T* tmp = (T*)(::operator new((size_t)(size * sizeof(T))));
        if (tmp == 0) {
            cerr << "out of memory" << endl;
            exit(1);
        }
        return tmp;
    }

    // deallocate的实际实现,简单封装delete
    template <class T>
    inline void _deallocate(T* buffer) { ::operator delete(buffer); }

    // construct的实际实现,直接调用对象的构造函数
    template <class T1, class T2>
    inline void _construct(T1* p, const T2& value) { new(p) T1(value); }

    // destroy的实际实现,直接调用对象的析构函数
    template <class T>
    inline void _destroy(T* ptr) { ptr->~T(); }

    template <class T>
    class allocator {
    public:
        typedef T           value_type;
        typedef T*          pointer;
        typedef const T*    const_pointer;
        typedef T&          reference;
        typedef const T&    const_reference;
        typedef size_t      size_type;
        typedef ptrdiff_t   difference_type;

        // 构造函数
        allocator(){ return; }
        template <class U>
        allocator(const allocator<U>& c){}

        // rebind allocator of type U
        template <class U>
        struct rebind { typedef allocator<U> other; };

        // allocate,deallocate,construct和destroy函数均调用上面的实际实现
        // hint used for locality. ref.[Austern],p189
        pointer allocate(size_type n, const void* hint = 0) {
            return _allocate((difference_type)n, (pointer)0);
        }
        void deallocate(pointer p, size_type n) { _deallocate(p); }
        void construct(pointer p, const T& value) { _construct(p, value); }
        void destroy(pointer p) { _destroy(p); }

        pointer address(reference x) { return (pointer)&x; }
        const_pointer const_address(const_reference x) { return (const_pointer)&x; }

        size_type max_size() const { return size_type(UINT_MAX / sizeof(T)); }   
    };
} // end of namespace myalloc

自己编写的allocator为vector分配空间

#include <vector>
int main()
{
    std::vector<int, my_alloc::allocator<int> > v;
    // Do something;
    return 0;
}

该实现符合STL标准,但是通过不了GCC编译器,原因是SGI STL的allocator并不完全符合STL规范。在gcc9.2.0(mingw-w64 on msys2)里,上面这个“最简单的allocator实现”微小改动(给set_new_handler、cerr、endl三处加上std::)以后是可以编译通过。
在这里插入图片描述

SGI STL 默认配置器:std::alloc 详解

上面实现的满足STL标准的allocator只是简单的实现内存配置/释放,即对new和delete的浅包装,SGI中拥有其独特的操作来优化alloc的性能

alloc总体架构

1.构造和析构基本工具construct()destory <stl_construct.h>
2.空间的配置与释放工具 一级配置器、二级配置器<stl_alloc.h>
3.调用系统内存函数<stl_uninitial.>

在这里插入图片描述

new操作

class Foo{....}
Foo *pf =new Foo;
delete pf

上述代码new操作主要分为两个阶段的操作
1.调用::operator new 配置内存
2.调用构造函数 Foo()构造对象内容
delete也包含两个操作:
1.调用Foo:~Foo()将对象析构
2.调用::operator delete 释放内存

STL 中 内存配置操作由 alloc:allocate 负责
内存释放由alloc::deallocate负责,对象构造由::construct 负责,对象析构由
::destroy负责

destroy

直接使用模板编程调用析构函数

template<class T>
inline void destroy(T *pointer)
{
 pointer->~T();
}

construct

template<class T1,class T2>
inline void construct (T1*p,const T2& value)
{
 new(p) T1(value);
}

在SGI源码中加入了第二版destroy,主要根据trivial来特化实例
在这里插入图片描述

allocate

在SGI中,alloc优化了申请内存和释放的性能。拿vector来举例,申请一个vector时,我们调用alloc为其申请内存空间。
在这里插入图片描述
在SGI中将alloc分为一级适配器和二级适配器,以应用于内存大小不同的场景。大于128bytes直接调用一级alloc,小于则使用二级alloc。二级适配器采用维护16个自由链表来分配内存,这主要是为了解决小型区块可能造成的内存碎片问题。
在这里插入图片描述

空间释放函数deallocate

该函数首先会判断区块大小,大于128bytes调用一级配置器,小于128bytes就找到对应的自由链表,将区块回收

另外的内存处理工具

STL 定义了5个全局函数,作用容器配置空间。
1.构造函数 construct
2.析构函数 destroy
3.uninitialized_copy ->copy()
4.uninitialized_fill->fill()
5.uninitialized_fill_n->filln()
在这里插入图片描述

总结

本文简单介绍了STL组件之一空间配置器,先从标准接口来简要的理解allocator的功能紧接着用templet编程写了一个简单的allocator,然后记录了SGI 中利用traits编程技法来特化提高函数效率,包括一二级适配器优化内存管理的过程,最后介绍了另外几个内存全局函数。本篇文章并未具体细节代码进行讲解是对《STL源码剖析》框架上的总结,若读者对具体代码有兴趣,可以直接读原书。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/24698.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MindFusion JS Chart 2.0 Crack

一个用于图表、仪表和仪表板的库。MindFusion JS Chart 结合了 2D 和 3D 图表、财务图表、仪表和仪表板。优雅的 API、丰富的事件集、无限数量和类型的数据系列以及您在JavaScript和HTML中创建完美数据可视化可能需要的一切。 特征 常见图表类型 创建交互式线图、 面积图、 气泡…

深入浅出scala之变量定义(P11-15)

文章目录1. 变量定义2.数据类型3.数值类型4.浮点类型1. 变量定义 基本语法: 变量定义一定要初始化 var|val变量名[: 变量类型] .变量值使用var或者val定义一个变量。 使用var(variable)声明变量&#xff0c;可以被重新赋值。 //定义变量a2,手动指定类型为Int,此时需要保证所…

如何完成视频合并操作?这几个方法值得一试

我们在拍摄视频vlog的时候&#xff0c;不可能持续、完整地拍一整天&#xff0c;而是通过很多视频素材中&#xff0c;挑选几段有意义的部分&#xff0c;将他们剪辑出来&#xff0c;然后再进行合并。大家可能会觉得视频剪辑很难学&#xff0c;其实不然&#xff0c;我们借助一些专…

[附源码]java毕业设计小说网站的设计与实现1

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

NVIDIA AGX Xavier 部署 CUDA-PointPillars

背景&#xff1a; CUDA-PointPillars 在X86 NVIDIA GeForce GTX 1060 使用自家激光雷达数据跑通并优化后&#xff0c;部署到边缘设备NVIDIA AGX Xavier&#xff0c;出现了好多问题&#xff0c;记录下来&#xff0c;以备后用。 参考&#xff1a; NVIDIA Jetson AGX Xavier安装…

SpringBoot整合Memcached缓存技术/JetCache缓存技术以及J2Cache缓存技术怎么在Spring Boot中配置

写在前面&#xff1a; 继续记录自己的SpringBoot学习之旅&#xff0c;这次是SpringBoot应用相关知识学习记录。若看不懂则建议先看前几篇博客&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 3.5.1.6 Memcached缓存技术使用 3.5.1.6.1 下载安装…

torch包下载和安装失败的解决

今天打算使用python的 torch包的时候&#xff0c;输入pip install torch&#xff0c;在pycharm下载一直失败。 报错信息里面提示一开始是pip版本出错&#xff1a; WARNING: You are using pip version 20.0.2, however version 20.2.3 is available. 导致我一整天都在更新pip&…

软件工程毕设项目 计算机SSM毕业设计【源码+论文】

文章目录前言 题目1 : 基于SSM的旅游资源网站 <br /> 题目2 : 基于SSM的中药店商城网站 <br /> 题目3 : 基于SSM的汽车租赁网站<br /> 题目4 : 基于SSM的汉服文化平台网站 <br /> 题目5 : 基于SSM的校园疫情师生防疫登记备案系统 <br /> 题目6 :…

JS——【案例】图片轮播图(自动轮播/手动点击/悬停显示)[技术栈:html、css、JavaScript]

1、效果&#xff1a; 2、需求&#xff1a; 3、代码实现&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"&…

【飞桨Paddle】RTSP视频流和PP-Human实时行人分析

PP-Human是基于飞桨深度学习框架的业界首个开源的实时行人分析工具&#xff0c;支持图片/单镜头视频/多镜头视频多种输入方式&#xff0c;功能覆盖多目标跟踪、属性识别和行为分析&#xff0c;兼容图片、视频、在线视频流多种数据格式输入。 环境准备 环境要求&#xff1a; Pa…

蓝牙耳机哪款音质最好?公认音质好的蓝牙耳机品牌

耳机作为日常生活的调剂品&#xff0c;从性能到外观&#xff0c;再到音质让我对真无线蓝牙耳机的综合性能惊艳&#xff0c;蓝牙技术的成熟开启了无线传输模式&#xff0c;面对琳琅满目的无线蓝牙耳机&#xff0c;很多人一时之间无从下手&#xff0c;不知道口碑最好的蓝牙耳机是…

【空间/通道注意模型:Nest连接:IVIF】

NestFuse: An Infrared and Visible Image Fusion Architecture Based on Nest Connection and Spatial/Channel Attention Models &#xff08;NestFuse: 基于Nest连接和空间/通道注意模型的红外和可见光图像融合架构&#xff09; 我们提出了一种新颖的红外和可见光图像融合…

分布式技术——分布式事务原理与实战

摘要 分布式事务是分布式系统中非常重要的一部分&#xff0c;最典型的例子是银行转账和扣款&#xff0c;A 和 B 的账户信息在不同的服务器上&#xff0c;A 给 B 转账 100 元&#xff0c;要完成这个操作&#xff0c;需要两个步骤&#xff0c;从 A 的账户上扣款&#xff0c;以及…

sqli-labs/Less-36

这一关和上一关一样都是get请求形式的 我们首先判断一下注入类型是否为数字型 输入如下 id1 and 12 正常回显了 说明属于字符型 然后判断是单引还是双引 输入1 回显如下 不好 遇到转义了 需要宽字节注入帮助逃逸才行 于是将注入语句改成了1%df 回显如下 出现报错信息 从…

聊聊Spring Cloud Gateway 动态路由及通过Apollo的实现

在之前我们了解的Spring Cloud Gateway配置路由方式有两种方式 1.通过配置文件 spring:cloud:gateway:routes:- id: testpredicates:- Path/ms/test/*filters:- StripPrefix2uri: http://localhost:9000 2.通过JavaBean Beanpublic RouteLocator routeLocator(RouteLocatorB…

最新科目一攻略(新规)

一、*新规题 1、学法减分学习和满分教育 学法减分学习网上学习3日内累计满30分钟且考试合格&#xff0c;一次扣减1分现场学习满1小时且考试合格&#xff0c;一次扣减2分参加组织的交通安全公益活动的&#xff0c;满1小时&#xff0c;一次扣减1分【易考】饮酒后受过处罚&#xf…

[内排序]八大经典排序合集

文章目录1 排序的基本概念1.1 什么是排序1.2 排序的稳定性1.3 内排序和外排序2 插入排序2.1 直接插入排序1. 排序思路2. 直接插入排序实例3. 排序算法4. 算法分析5. 折半插入排序 / 二分插入排序5.1 排序思路5.2 排序算法5.3 算法分析2.2 希尔排序1. 排序思路2. 希尔排序实例3.…

免费查题接口

免费查题接口 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 查题校园题库&#xff1a;查题校园题库后台&#xff08;点击跳转&a…

NodeJs实战-待办列表(7)-connect组件简化代码

NodeJs实战-待办列表7-connect组件简化代码什么是connectconnect demo 程序conenct 应用到服务端验证添加完成什么是connect connect demo 程序 安装 conncet、connect-query 组件 npm install connect npm install connect-query编写 demo 程序&#xff0c;保存到 test_conn…

阿里高工内产的 SpringBoot 实战派手册仅发布一天霸榜Github

近年来&#xff0c;Spring Boot 是整个Java社区中最有影响力的项目之一&#xff0c;常常被人看作是Java EE( Java Platform Enterprise Edition )开发的颠覆者&#xff0c;它将逐渐替代传统SSM ( Java EE互联网轻量级框架整合开发——Spring MvCSpringMyBatis&#xff09;架构。…