【STL】SGI空间配置器 Allocator

一起了解C++ SGI版本allocator 一起了解C++ SGI版本allocator前言为什么要有allocator?四个主要功能一步步看看源码 前言 这也是面试官喜欢问的东西,咱们这次整理清楚,做好准备。 为什么要有allocator? 《stl源码剖析》提到,stl库的六大组件:容器、算法、迭代器、仿函数、适配器、配置器(allocator)。 这个问题在《primer C++》中写的很清楚。作者认为,就不应该将allocation和construction搞在一起(对没错,说的就是new),当然delete也很挫。为什么呢?因为有的时候我确 阅读详情

       本篇将主要总结归纳《STL源码剖析》的空间配置器的相关STL实现。在此之前,我们也将总结归纳一些基本的C++知识和技法。


一、C++基础知识--3种new的方式

       在C++中,包含3种new形式,分别是
  •  new / delete
  •  operator new / operator delete
  •  placement new


1. new, operator new,  delete, operator delete

       在C++中,我们所习惯的C++内存配置操作和释放操作是如下这样的:
class Foo{ ... };
Foo *pf = new Foo;
delete pf

       这里的new即为上述的第一种情况,也称new operator。他通常包含如下3个操作:
  • new: 调用 ::operator new 分配内存                      delete:  调用 Foo::~Foo()
  •         调用 Foo::Foo()构造对象内容                                   调用 ::operator delete 释放内存
  •         返回相应的指针
       new operator 和 delete operaror 是对应在堆中内存的申请和释放,且二者无法被重载。

       operator new/ operator delete 是可以根据operator+一样进行重载的。其工作的方式如下:
  • 只分配所要求的空间,不调用对象的构造函数。当无法满足所要求分配空间时,则有 new_handler,则调用new_handler, 否执行bad_alloc(如果有抛出异常的请求),否则返回0.
  • 同时,重载时,返回类型必须是void* ,重载时,第一个参数必须是表达要求分配空间的大小,类型是size_t,重载可以带其他参数。
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;

class Foo
{
public:
    Foo() { std::cout << "constructor of Foo" << std::endl; }
    ~Foo() { std::cout << "destructor of Foo" << std::endl;}

    // override operator new
    void* operator new(size_t sz, string str)
    {
        std::cout << "operator new size "<< sz
            <<" with string "<< str << std::endl;
        // allocate memory
        return ::operator new(sz);
    }

    // override operator delete
    void operator delete(void* ptr)
    {
        std::cout<<"operator delete" << std::endl;
        // delete memory
        ::operator delete(ptr);
    }
};

int main()
{
    // new operator
    Foo *pFoo = new("Foo class") Foo;
    delete pFoo;

    return 0;
}
运行结果如下:

这里的 ::operator new 和 ::operator delete 对应于C语言就是 malloc和free,只进行内存分配,而且必须配套使用。


2. placement new

       placement new 是重载operator new的一个标准的,全局的版本。函数原型如下:
void* operator new(size_t, void *p) throw() { return p; }
placement new允许用户将一个对象放置到一个特定的地方。
char *buf= new char[sizeof(Foo)];
// 在已有的内存地址上调用构造函数。
Foo* pi = new(buf) Foo; 
       所以,使用placement new的主要原因是,用new分配缓存时,调用默认构造函数,可能导致效率上的不佳。若没有默认的构造函数,则会发生编译错误。如果想在预分配的内存上创建对象,用缺省的new是行不通的,只能通过placement new进行构造。
另外有三种方式进行提前分配缓存:
  • 在堆上进行分配,也就是 char *buf = new char[sizeof(Foo)];
  • 在栈上进行分配  char buf[N * sizeof(Foo)];
  • 直接通过地址进行, void* buf = reinterpret_cast<void *(0xABDC);

二、STL空间配置器allocator

1. SGI特殊的空间配置器,std::alloc

       正如上面new运算符包含2个操作过程,包括分配内存空间,释放内存。STL allocator将这两阶段区分开,内存配置由alloc::allocate()负责, 内存释放由alloc::deallocate()负责,对象构造由 ::contruct() 负责, 对象析构由 ::destroy() 负责。

2. 构造和析构基本工具: construct() 和 destroy()


       上述的construct()接受一个指针p和一个初值value,该函数的用途就是将初值设定到所指的空间上,也就是上述所受的placement new。
       同时上述利用value_type()获得所指迭代器所指对象的型别,再利用__type_traits<T>判断该型别的析构函数是不是trivial的。non trivial即至关重要,需要调用析构函数,进行释放,如果是trivial的,即如数值类别的,则不需要。这样的设定是为了能够提高效率。
#include <new.h>  // 使用placemen new

template <class T1, class T2>
inline void construct(T1* p, const T2& value) {
    //placement new, 调用T1::T1(value), p为已申请的内存缓存
    new (p) T1(value);  
}

// 以下为destroy()的第一版本,接受一个指针
template <class T>
inline void destroy(T* pointer){
     // 这是placement new 的标准操作,先调用析构函数
    pointer->~T();   
}

// 以下是destroy() 的第二版本,接受两个迭代器,设法找出元素的数值型别
// 进而利用__type_traits<> 调用适当的操作
template <class ForwardIterator>
inline void destroy(ForwardIterator first, ForwardIterator last){
    __destroy(first, last, value_type(first));
}

// 判断元素的数值型别(value_type)是否有trivial destructor,
template <class ForwardIterator, class T>
inline void __destroy(ForwardIterator first, ForwardIterator last, T*)
{
    typedef typename __type_traits<T>::has_trivial_destructor trivial_destructor;
    __destroy_aux(first, last, trivial_destructor);
}

// 如果元素的数值型别(value type)有nontrivial destructor, 就是需要显示调用析构函数
template<class ForwardIterator>
inline void 
__destroy_auxx(ForwardIterator first, ForwardIterator last, __false_type){
    for(; first < last; ++ first) 
        destroy(&*first);
}

// 如果元素的数值型别(value type)有trivial destructor, 比如数值类型
template<class ForwardIterator>
inline void __destroy_auxx(ForwardIterator, ForwardIterator, __true_type){}

// 以下是destroy() 对第二版本针对迭代器为char* 和 wchar_t* 的特化版本
inline void destroy(char*, char*)()
inline void destroy(wchar_t*, wchar_t*)()


3. 空间的配置和释放  std::alloc

对象构造前的空间配置和对象析构后的空间释放,由<stl_alloc.h>负责,主要考虑以下几个准则
  • 向system heap 要求空间
  • 考虑多线程(multi_thread)状态
  • 考虑内存不足时的应变措施
  • 考虑过多“小型区块”可能造成的内存碎片(fragment)的问题。  --> 二级配置器
SGI STL以malloc()和free()完成内存的配置和释放。

        正如上面的准则4,SGI采用双层级配置器,第一级配置器直接使用malloc和free,用来配置大于128byte的区域块;第二级配置器采用memory pool管理方式来配置小的区域块。其中区域块利用free_list来进行管理8,16,24, ..., 128等共16个等级的小额区域块。


一二级配置器军采用以下接口进行包装以符合STL规格:

template<class T, class Alloc>
class simple_alloc {
public:
    static T* allocate(size_t n) { return n == 0 ? 0 : (T*) Alloc::allocate(n * sizeof(T)); }
    static T* allocate(void) { return (T*) Alloc::allocate(sizeof(T)); }
    static void deallocate(T *p, size_t n) { if(0 != n) Alloc::deallocate(p, n * sizeof(T)); }
    static void deallocate(T *p) { Alloc::deallocate(p, sizeof(T)); }
};





3.1 第一级配置器__malloc_alloc_template

        第一级配置器以malloc(), free(), realloc()等C函数执行实际的内存配置,释放,重配置等操作,并实现了类似C++ new_handler的机制。因为不是用C++的::operator new来分配内存的。这里的new handler机制,就是如果::operator new 无法完成任务,在丢出std::bad_alloc异常状态之前,会先调用客户端制定的处理历程。  其中,第一级配置器还分成两种情况,一是如果内存足够,直接调用allocate, deallocate, 和 reallocate,对应malloc, free, 和realloc。 当内存不足时,也就是out of memory, 就调用相应的oom_malloc(), oom_realloc()。


3.2 第二级配置器 __default_alloc_template

        第二级配置器是为了避免太多小额区块造成的内存碎片而存在的。当区块大于128byte时,交给第一级配置器,否则,则以内存池(memory pool)管理,交给第二级配置器,又称次层配置(sub_allocation),其用一个自由链表free_list进行维护。配置器除了负责配置,也负责回收,同时也会将所有申请的小额区块主动上调到8的倍数,比如30 bytes->32 bytes。维护16个free_list分别管理16个不同区块,分别是8 bytes, 16 bytes, ..., 128 bytes,方便分配和回收。


这里维护free_list的节点数据结构如下:

union obj {
    union obj* free_list_link;
    char client_data[1]; 
};

        <STL源码剖析>上说,此结构一物二用的结果是,不会为了维护链表所必须的指针而造成一种内存浪费。上述用到了 柔性数组 的概念。这里的前4字节用来存储指向的地址。这里的一物二用,是指,client_data指向的是当前首地址,同时也可以直接通过obj.client_data获取内容。而free_list_link本身可以看做一个指针,指向一个obj。需要注意的是,client_data里的值可以是0或者1。其长度大小由客户端设定。以下给出一个示例代码:
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
using namespace std;

struct Bar
{
    int bar;
    char client_data[0];
};
Bar *pObj;

int main()
{
    char str1[] = "hello world";

    pObj = (Bar*)malloc(sizeof(Bar) + strlen(str1) + 1);
    if(NULL != pObj) {
        pObj->bar = 1;
        strcpy(pObj->client_data, str1);
    }
    cout << "pObj: " << pObj->bar << " " << pObj->client_data << endl;

    free(pObj);

    return 0;
}
运行结果如下:



        回到正文。
               
        以下是第二级配置器的实现源码:

enum {__ALIGN = 8};  //小型区块的上调边界
enum {__MAX_BYTES = 128};   //小型区块的上界
enum {__NFREELISTS = __MAX_BYTES/__ALIGN};   //free-list个数

template <bool threads, int inst>
class __default_alloc_template {

private:
	/*将bytes上调至8的倍数
	用二进制理解,byte整除align时尾部为0,结果仍为byte;否则尾部肯定有1存在,加上
	align - 1之后定会导致第i位(2^i = align)的进位,再进行&操作即可得到8的倍数
	*/
	static size_t ROUND_UP(size_t bytes) {
        return (((bytes) + __ALIGN-1) & ~(__ALIGN - 1));
  	}
private:
	union obj {   //free-list的节点
	    union obj * free_list_link;
	    char client_data[1];    /* The client sees this.     */
	};

private:
	//16个free-lists
	static obj * __VOLATILE free_list[__NFREELISTS]; 
	//根据区块大小,找到合适的free-list,返回其下标(从0起算)
  	static  size_t FREELIST_INDEX(size_t bytes) {
        return (((bytes) + __ALIGN-1)/__ALIGN - 1);
  }
  //返回一个大小为n的对象,并可能编入大小为n的区块到相应的free-list
  static void *refill(size_t n);
  //配置一大块空间,可容纳nobjs个大小为“size”的区块
  //如果配置nobjs个区块有所不便,nobjs可能会降低
  static char *chunk_alloc(size_t size, int &nobjs);

  //Chunk allocation state
  static char *start_free;
  static char *end_free;
  static size_t heap_size;

public:
	static void * allocate(size_t n);
	static void * deallocatr(void *p, size_t n);
	static void * reallocate(void *p, size_t old_sz, size_t new_sz);
};

//以下是static data member的定义与初值设定
template <bool threads, int inst>
char * __default_alloc_template<threads, inst>::start_free = 0;

template <bool threads, int inst>
char * __default__alloc_template<threads, inst>::end_free = 0;

template <bool threads, int inst>
size_t __default_alloc_template<threads, inst>::heap_size = 0;

template <bool threads, int inst>
__default_alloc_template<threads, inst>::obj * volatile
__default_alloc_template<threads, inst>::free_list[__NFREELISTS] = 
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, };

         以下是 空间配置函数allocate()的实现:
//n must be > 0
static void * allocate(size_t n)
{
    obj * __VOLATILE * my_free_list;
    obj * __RESTRICT result;

    //大于128就调用第一级配置器
    if (n > (size_t) __MAX_BYTES) {
        return(malloc_alloc::allocate(n));
    }
    //寻找16个free-lists中适当的一个
    my_free_list = free_list + FREELIST_INDEX(n);
    result = *my_free_list;
    if (result == 0) {
    	//没找到可用的free-list,准备重新填充free-list
        void *r = refill(ROUND_UP(n));
        return r;
    }
    //调整free-list,指向拨出区块的下一个区块
    *my_free_list = result -> free_list_link;
    return (result);
};

相应的示意如下:

        空间释放函数deallocate()

首先判断区块大小,大于128就调用第一级配置器,否则就找出相应的free_list,将区块回收。
// p不可以是0
static void deallocate(void *p, size_t n)
{
    obj *q = (obj *)p;
    obj * volatile * my_free_list;
    
    // 大于128就调用第一级配置器
    if(n > (size_t) __MAX_BYTES) {
        malloc_alloc::deallocate(p, n);
        return;
    }
    
    //寻找对应的free list
    my_free_list = free_list + FREELIST_INDEX(n);
    // 调整free list, 回收分块。
    q->free_list_link = *my_free_list;
    *my_free_list = q;
    
}


重新填充free lists refill()函数
当free_list中没有了可用区块时,为free list重新填充空间,新的空间从内存池(由 chunk_alloc()完成)。
//返回一个大小为n的对象,并且有时候会适当的free-list增加节点
//假设n已经适当上调至8的倍数
template <bool threads, int inst>
void* __default_alloc_template<threads, inst>::refill(size_t n)
{
    int nobjs = 20;
    //尝试获得nobjs个区块作为free-list的新节点
    char * chunk = chunk_alloc(n, nobjs);
    obj * __VOLATILE * my_free_list;
    obj * result;
    obj * current_obj, * next_obj;
    int i;

    //如果只获得一个区块,这个区块就分配给调用者使用,free-list无新增区块
    if (1 == nobjs) return(chunk);
    //否则调整free-list 纳入新节点
    my_free_list = free_list + FREELIST_INDEX(n);

    //在chunk这段连续内存内建立free-list
	result = (obj *)chunk;   //这一块准备返回给客户端
	//将free-list指向新配置的连续内存空间
	//allocate中my_free-list为0才进入本函数,故无需存储现在的*my_free-list,直接覆盖即可
	*my_free_list = next_obj = (obj *)(chunk + n);

	//将free-list的各节点串接起来     
	for (i = 1; ; i++) {
		current_obj = next_obj;
		next_obj = (obj *)((char *)next_obj + n);  //每一个区块大小为n
		if (nobjs - 1 == i) {  //最后一块
		    current_obj -> free_list_link = 0;
		    break;
		} else {
		    current_obj -> free_list_link = next_obj;
		}
	}
    return(result);
}

内存池(memory pool)中的chunk_alloc()
此函数用于给予free_list分配区块。注意,新加量的大小是原来的两倍,并再加上一个随着配置次数增加的越来越大的附加量。并且其中的nodjs采用pass by reference的形式,是因为参数将被修改为实际被分配的区域块大小。chunk_alloc取空间的原则如下:尽量从内存池中取,内存池不够了,才使用free-list中的可用区块。

//size此时已适当上调至8的倍数
template <bool threads, int inst>
char*
__default_alloc_template<threads, inst>::chunk_alloc(size_t size, int& nobjs)
{
    char * result;
    size_t total_bytes = size * nobjs;   //8的倍数
    size_t bytes_left = end_free - start_free;  //8的倍数

    if (bytes_left >= total_bytes) {  //情况1
    	//内存池剩余空间完全满足需求量
        result = start_free;
        start_free += total_bytes;
        return(result);
    } else if (bytes_left >= size) {  //情况2
    	//虽不足以完全满足,但足够供应一个(含)以上的区块
    	//从start_free开始一共total_bytes分配出去,其中前size个bytes给客户端,剩余的给free-list
        nobjs = bytes_left/size;
        total_bytes = size * nobjs;
        result = start_free;
        start_free += total_bytes;
        return(result);
    } else {
    	//内存池剩余空间连一个区块的大小都无法提供
        size_t bytes_to_get = 2 * total_bytes + ROUND_UP(heap_size >> 4);
        // 以下尝试将内存池中的残余零头分配完
        if (bytes_left > 0) {
            obj * __VOLATILE * my_free_list =
                        free_list + FREELIST_INDEX(bytes_left); //找到大小相同区块所在的free-list

            ((obj *)start_free) -> free_list_link = *my_free_list;  //将内存池剩余空间编入free-list中
            *my_free_list = (obj *)start_free;
        }
        //此时内存池的空间已用完
        //配置heap空间,用来补充内存池
        start_free = (char *)malloc(bytes_to_get);
        if (0 == start_free) {
        	//heap空间不足,malloc失败
            int i;
            obj * __VOLATILE * my_free_list, *p;
            //转而从free-lists中找寻可用的区块(其大小够用)
            for (i = size; i <= __MAX_BYTES; i += __ALIGN) {
                my_free_list = free_list + FREELIST_INDEX(i);
                p = *my_free_list;
                if (0 != p) {   //free-list尚有可用区块
                	//调整free-list以释出可用区块
                    *my_free_list = p -> free_list_link;
                    start_free = (char *)p;   //将改区块归还到内存池
                    end_free = start_free + i;
                    //再次从内存池中索要连续空间来满足客户端需求
                    return(chunk_alloc(size, nobjs));  //由于此时i >= size,故此次只会进入情况1/2
                }
            }
	    	end_free = 0;	//没有可用区块归还到内存池,内存池仍为空
	    	//调用第一级配置器,看out-of-memory机制是否能改善
            start_free = (char *)malloc_alloc::allocate(bytes_to_get);
            
        }
        //内存池获得新的连续空间
        heap_size += bytes_to_get;
        end_free = start_free + bytes_to_get;
        //再次尝试分配
        return(chunk_alloc(size, nobjs));
    }
}


参考文献:



SGI STL空间配置器(allocator)设计原理与源码剖析(一) 概述 、SGI标准的空间配置器:std::allocator 、SGI特殊空间配置器:std::alloc 、构造和析构基本工具:construct() 和 destroy() 、空间的配置与释放:std::alloc 、一、二级空间配置器简述 阅读详情

相关推荐

SGI STL空间配置器(allocator)设计原理与源码剖析(二)

一级空间配置器 _ _malloc_alloc_template剖析 、二级空间配置器 _ _default_alloc_template剖析 、空间配置函数allocate() 、空间释放函数deallocate() 、重新填充free lists 、内存池(memory pool)

ZY-JIMMY 1113

STL源码分析:SGI STL的内存管理 allocator

前言 今天来分析一个STL的alloc的源码,STL这么精妙的东西当然是会自己管理内存的啦~~· 整体看下来,STL的内存管理比操作系统内存管理的简单太多了。。。 整体轮廓 STL源码里面,有两个allocator,一个被称为__malloc_alloc_template,另外一个被称为__default_alloc_template。 __malloc_alloc_template被称为一级内存...

jmhIcoding 818

LangFlow开源神器:拖拽构建AI Agent与MCP协议集成实战

LangFlow 15万星开源神器:拖拽搭建 AI Agent,一键部署 API / MCP / JSON 在AI应用开发领域,传统编码方式往往需要处理复杂的API调用、数据处理和流程编排,这让很多开发者望而却步。LangFlow作为GitHub上获得15万星的开源项目,通过可视化拖拽的方式彻底改变了AI Agent的开发体验。本文将完整介绍如何使用LangFlow快速构建功能强大的AI Agent,并实现API、MCP协议和JSON配置的一键部署。 1. LangFlow与AI Agent核心概念解析 1

weixin_33717117的博客 931

SGI-STL学习笔记之allocator

空间配置器的标准接口:allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_refrence allocator::size_type allocator::difference_type pointer allocator::allocate(size_type n,const void*=0) //配置空

冰枫的随笔 3673

Ubuntu安装pytorch3d的最便捷方法【原创】

Ubuntu安装pytorch3d的最便捷方法

qq_54900679的博客 2924

从零开始:Basler相机与pylon Viewer的工业视觉入门指南

本文详细介绍了Basler相机与pylon Viewer在工业视觉系统中的入门指南,涵盖硬件连接、软件安装、核心功能解析及实战案例。通过pylon Viewer的全面控制和参数调整功能,帮助新手快速掌握工业视觉检测技术,提升生产效率。

julia4scientist的博客 1134

SGI STL中的空间配置器(Allocator)图文详解

SGI STL中的空间配置器图文详解 1 为什么需要内存配置器? 1)在STL中,为了实现各种容器,需要分配内存,这个过程中如果直接在堆上开辟空间,可能会造成内存外碎片化。 1.内碎片化是指因为内存对齐、或者是按照其他的分配方式导致的已经分配的内存无法得到充分利用,比如需要5个字节,实际分到了8个字节的情况。 2.外碎片化是指,内存中有足够的空间,但是这些空间都是不连续的零散空间,无法分配给申请内...

AlexanderGan的博客 930

Arduino程序设计(十)8×8 共阴极LED点阵显示(MAX7219)

本文主要介绍8×8 LED点阵显示实验,分别是:1、介绍MAX7219点阵模块;2、点阵显示部分图形;3、点阵显示数字 0~9 及 26 个英文字母。1、通过上述两个点阵实验,了解了8*8点阵显示的基本原理;2、通过SPI通信控制点阵显示,学会了Arduino用SPI通信方式控制外设。

Alice的博客 1万+

SGI STL 源码解读之Allocator

为了进一步了解Allocator的运作原理,我们以下面的使用作为例子,解读其实现细节。      std::allocatorint>MyAll;      MyAll.allocate(10);      以上代码调用SGI STL的allocator,分配10个int型的空间。下面的分析使用SGISTL源代码allocator.cpp,并加上我的理解注释,建议参考侯捷的书做了解。但我目前

行者无疆的专栏 3871

冷门但实用:Python爬取微信公众号历史文章,突破微信反爬限制(2025有效)

2025年微信公众号爬取的核心是「冷门方法+指纹伪装」,而非常规接口破解,itchat-uos+Playwright组合是突破设备指纹的关键;登录态持久化、动态Token实时获取、频率严格控制是避免被封禁的三大核心;文章内容解析需解决2025新增的编码混淆问题,chardet+BeautifulSoup是冷门但有效的方案;合规是前提,爬取频率、数据用途需严格遵守平台/法律规则。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 3775

解决Gradle中NPM命令失效问题

摘要:本文分析了IntelliJ IDEA中Gradle执行npm命令失败的问题,报错显示"npm"文件不存在。通过确认npm安装路径、检查系统PATH与Gradle环境的差异,提出两种解决方案:1) 在build.gradle中使用npm绝对路径;2) 通过launchctl修改用户PATH。实例展示了如何修改Gradle脚本或系统配置来解决该问题,指出跨平台开发中环境变量配置的重要性。文章为开发者提供了处理类似问题的实用方法。

2501_90323865的博客 90

STL源码剖析(侯捷版本) —— 第二章 空間配置器 allocator(一)

在 STL 的使用中,空间配置器是用户“不需要关注”的部分。它始终隐藏在 STL 组件(如容器)的背后,默默完成内存分配和管理的任务。用户使用 STL 容器时,很少直接接触空间配置器的细节。STL 的 Allocator 是一个标准化的内存分配接口,定义了类型别名、内存分配与释放,以及对象构造与销毁的功能。它通过泛型和嵌套类型支持不同对象类型的内存管理,是 STL 容器内存操作的核心工具。allocator::value_type:分配的对象类型。

weixin_42255569的博客 1718

YOLOv10改进策略【模型轻量化】| MoblieNetV3:基于搜索技术和新颖架构设计的轻量型网络模型

本文记录的是基于MobileNet V3的YOLOv10目标检测轻量化改进方法研究。的模型结构是通过得来的,其中的基础模块结合了的深度可分离卷积、的线性瓶颈和倒置残差结构以及MnasNet中基于挤压和激励的轻量级注意力模块,使模型在性能、效率和灵活性方面都具有显著的优势。本文在替换骨干网络中配置了原论文中的small和large2种模型,以满足不同的需求。

Limiiiing的博客 513

SGI-STL的空间配置器allocator

转载自https://www.cnblogs.com/LUO77/p/5824625.html 在STL中考虑到小型区块所可能造成的内存碎片问题,SGI STL设计了双层级配置器,第一级配置器直接使用malloc()和free();第二级配置器则视情况采用不同的策略:当配置区块超过128bytes 时,则视之为足够大,便调用第一级配置器;当配置区块小于128bytes时,则视之为过小,为了降低额外负担,便采用复杂的内存池的方式来整理,而不再求助于第一级配置器。 <stl_alloc.h>内定义了

weixin_44164489的博客 306

SAP_PP模块中MRP中信号灯简介

一、信号灯的作用二、常见的信号灯颜色及含义三、信号灯的来源四、常见场景示例示例1:物料满足所有需求示例2:生产订单已延迟示例3:缺料或未产生计划订单五、相关事务码参考六、如何应对红色或黄色信号灯?七、前台操作说明在 SAP PP 模块中,**MRP(物料需求计划)运行结果中的“信号灯”是一种非常直观的可视化提示工具,用于帮助用户快速识别物料计划是否存在异常或需要关注的问题。这些信号灯通常出现在MD04(库存/需求清单)、MD05(单物料MRP清单)、MD07(MRP列表)**等事务代码的界面中。

我小时候很黑的博客 621

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

STL 配置器(allocator)

配置器:负责空间配置与管理,从实现的角度来看,配置器是一个实现了动态空间配置、空间管理、空间释放的 class template。 空间配置器:整个 STL 的操作对象(所有的数值)都存放在容器之内,而容器一定需要配置空间以存放内容。 什么是 allocator?allocator 有什么用? 我们需要对 C++ 的 allocator 的堆内存接口调用顺序有个清晰的认识,如下图所示。 allocator 堆内存管理接口 STL 的容器(eg: vector、stack、deque等)有一个共同特征,就是

南宫封清的博客 1353

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

SGI STL 空间配置器(allocator)源码剖析

空间配置器的作用 我们知道,stl中的数据都是放到容器中的,容器需要存储空间,空间配置器就是负责容器存储空间的分配、回收等一系列内存操作。 STL标准规范中描述的allocator模版类的必要声明: Constructors // Constructors used to create allocator objects. allocator(); // Default constr

3025

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

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

allocator笔记

TGX的博客 615

STL 学习之空间配置器(allocator)

空间配置器(allocator)  学习(一)allocator必要接口以及SGI的第一级配置器    allocator不一定操作内存,也可以直接向硬盘取空间。    简单说就是管理容器的资料的空间的工具。    根据规范,allocator的必要接口为:    allocator::value_type allocator::pointer allocator::const_pointer a...

zxzamt的博客 581

空间配置器(SGI-STL)

理解 是一种管理空间的机制,对空间进行分配、回收 重要性:整个STL的操作对象都存放在容器中,容器需要配置空间置放数据。空间配置器为各容器实现了对空间的高效管理 为什么不直接用new/delete? 用户自己管理空间,容易内存泄漏 频繁申请小的内存空间,造成内存碎片 频繁调用函数过程中要出栈压栈,效率低 会产生额外的空间浪费(申请的空间大小+对空间管理的空间) 可能申请失败 为什么不说allo...

amara 545

STL源码剖析之allocator(1)

空间配置器(allocator)这个概念在阅读源码之前我根本没有听过,原以为内存分配都是使用new和delete运算符(注意和operator new、placement new、operator delete以及placement delete不同)。在实际使用STL编程时也很少会遇到自己去实现一个空间配置器的情况。事实上,STL容器背后都要依靠空间配置器去分配空间。在阅读容器等STL...

aihuaiwan0357的博客 177

STL-空间配置器(allocator)

SGI空间配置器allocator的标准接口allocator::value_type allocator::pointer allocator::const_pointer allocator::reference allocator::const_reference allocator::size_type allocator::diffrence_type allocator::rebind

Linkin_ygw的博客 635

STL空间配置器--《STL源码剖析》读书笔记

STL空间配置器(allocator)在所有容器内部默默工作,负责空间的配置和回收。STL标准为空间配置器定义了标准接口(可见《STL源码剖析》P43)。而具体实现细节则由各编译器实现版本而不同。下面介绍SGI STL中的allocator(实际叫alloc)配置器。文章末附SGI STL源码下载地址 一个简单的allocator配置器 首先我们来看一个SGI STL中符合标准,名为alloc

WUDAIJUN的博客 3026

STL源码学习——空间配置器

前言最近开始找实习了,对于STL的实现,一知半解,挺多认识都停留在表层,所以还是想看一看源码,所以找了侯捷的《STL源码剖析》——源码之前,了无秘密。我并不打算第一遍就把它全部弄懂,好的知识和代码总是需要反复咀嚼才能领悟其思想,也许以后会再读很多遍。最近时间比较紧张,准备面试,查漏补缺,所以都没什么时间写博客,本来希望赶赶进度自己把这本书大致地看一遍就好,但是现在还是些了博客,强迫自己慢下来,把学的

jiange_zh的博客 1607

STL学习笔记--2、空间配置器 allocator

STL allocator alloc

Cherryuuuu 3285
上一篇: 【leetcode】94. Binary Tree Inorder Traversal------Morris Traversal
下一篇: 【Algorithm】Manacher's Algorithm
小do在努力
博客等级 码龄16年 58粉丝 161原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值