1. 程式人生 > >STL-空間配置器剖析

STL-空間配置器剖析

         網上有很多對於STL空間配置器原始碼的剖析,之所以這麼多人去剖析空間配置器,我覺得是真的設計的太好,而且剖析空間配置器的架構的設計對於C++學者來說是一個不錯的提高能力的專案,所以加入到這個解剖大軍中來。

      參照了侯捷的《STL原始碼剖析》,原本直接看原始碼不懂得東西,突然間豁然開朗。再次寫下自己對於STL空間配置器的一點點理解。

   要了解空間配置器,有一張圖是必看的:


    這張圖是一級空間配置器宇二級空間配置器的封裝方式與呼叫。從此圖我們們可以看到其實空間配置器是分為兩級的,而這裡所謂的兩級並沒有高低之分,它們之間的區別就是看你想要申請記憶體空間的大小。如果申請的記憶體大小超過128,那麼空間配置器就自動呼叫一級空間配置器。反之呼叫二級空間配置器。而且在這裡要說明的是空間配置器預設使用的是一級空間配置器。

 一.   一級空間配置器:

   一級空間配置器就比較簡單了,STL原始碼中的一級空間配置器命名為class __malloc_alloc_template ,它很簡單,就是對malloc,free,realloc等系統分配函式的一層封裝,我向這也是為什麼這麼取名的原因。

     原始碼中的一級空間配置器也不難看懂,懂了他的思想也就不難寫出如下的程式碼:   

<span style="font-family:Microsoft YaHei;font-size:14px;">template<int inst>//非型別模板引數
class MallocAllocTemplate//一級空間配置器(malloc,free,realloc)
{
public:
	static void* Allocate(size_t n)
	{
		void* ret = malloc(n);
		if (0 == ret)
			ret = OomMalloc(n);
		return ret;
	}
	static void Deallocate(void* p)
	{
		free(p);
	}
	static void* Reallocate(void* p, size_t newsize)
	{
		void* ret = realloc(p, newsize);
		if (ret == 0)
			ret = OomRealloc(p, newsize);
		return ret;
	}
private:
	static void* OomMalloc(size_t n)//呼叫自定義的控制代碼處理函式釋放並分配記憶體
	{
		ALLOC_FUN hander;
		void* ret;
		while (1)
		{
			hander = MallocAllocHander;
			if (0 == hander)
			{
				cout << "Out of memory" << endl;
				exit(-1);
			}
			hander();
			ret = malloc(n);
			if (ret)
			{
				rteurn (ret);
			}
		}
	}
	static void* OomRealloc(void* p, size_t newsize)//同上
	{
		ALLOC_FUN hander;
		void* ret;
		while (1)
		{
			hander = MallocAllocHander;
			if (0 == hander)
			{
				cout << "Out of memory" << endl;
				exit(-1);
			}
			hander();
			ret = realloc(p,newsize);
			if (ret)
			{
				rteurn(ret);
			}
		}
	}
	static void(*SetMallocHandler(void(*f)()))();//設定作業系統分配記憶體失敗時的控制代碼處理函式
	static ALLOC_FUN MallocAllocHander;

};
template<int inst>
ALLOC_FUN MallocAllocTemplate<inst>::MallocAllocHander = 0;//控制代碼函式初始化為0</span>

       一級空間配置器中沒有可以討論的,除了這個控制代碼函式:static void(*SetMallocHandler(void(*f)()))();對於一個C初學者來說想要看懂這個宣告有點難度,這是一個返回值,引數都為函式指標的一個函式指標。填起來有點繞,其實他就是一個函式指標,它指向的是一個控制代碼函式,這個控制代碼函式對於一級空間配置器是比較重要的。

        malloc,free,realloc等庫函式是向系統申請記憶體並且操作的函式。平時我們並不太會遇到記憶體空間分配不出來的情況,但是如果這一套程式是執行在伺服器上的,各種各樣的程序都需要記憶體。這樣頻繁的分配記憶體,終有一個時候,伺服器再也分配不出記憶體,那麼空間配置器該怎麼辦呢?這個函式指標指向的控制代碼函式就是處理這種情況的設計。

       MallocAllocHander()一般是自己設計的一種策略。這種策略想要幫助作業系統得到記憶體空間用以分配。所以,設計這個函式就是一個提升空間配置器效率的一個方法。一般是大牛去玩兒的。哈哈。如果並不像設計這個策略,就把控制代碼函式初始化為0.

二.    二級空間配置器:

    一級空間配置器說起來比較乏味,他只是一層系統函式封裝,真正酸爽的是二級空間配置器,裡面有很多很棒的設計。多的不說,先來看二級空間配置器的框架,上程式碼:

<span style="font-family:Microsoft YaHei;font-size:14px;">template<bool threads,int inst>
class DefaultAllocTemplate//二級空間配置器
{
private:
	enum{ ALIGN = 8 };
	enum{ MAX_BYTES = 128 };
	enum{ FREELISTSIZE = MAX_BYTES / ALIGN };
public:
	static void* Allocate(size_t n)
	{
		if (n > MAX_BYTES)
		{
			return MallocAllocTemplate<inst>::Allocate(n);
		}
		void* ret = NULL;
		size_t index = GetFreeListIndex(n);

		if (FreeList[index])//自由連結串列上有記憶體塊
		{
			obj* cur = FreeList[index];
			ret = cur;
			FreeList[index] = cur->listLink;
		}
		else   //呼叫refill從記憶體池填充自由連結串列並返回記憶體池的第一個記憶體塊
		{
			size_t bytes = GetRoundUpNum(n);
			return Refill(bytes);
		}
		return ret;
	}
	static void* Reallocate(void* p, size_t oldsize, size_t newsize)
	{
		void* ret = NULL;
		if (oldsize > (size_t)MAX_BYTES&&newsize > (size_t)MAX_BYTES)
			return (realloc(p, newsize));
		if (GetRoundUpNum(oldsize) == GetRoundUpNum(newsize))
			return p;
		ret = Allocate(newsize);
		size_t copysize = oldsize > newsize ? newsize : oldsize;
		memcopy(ret, p, copysize);
		DeAllocate(p, oldsize);
		return ret;
	}
	static void Deallocate(void* p, size_t n)
	{
		if (n > MAX_BYTES)//如果大於MAX_BYTES直接交還給一級空間配置器釋放
			return MallocAllocTemplate<inst>::Deallocate(p, n);
		else//放回二級空間配置器的自由連結串列
		{
			size_t index = GetFreeListIndex(n);
			obj* tmp = (obj*)p;
			tmp->listLink = FreeList[index];
			Freelist[index] = tmp;
		}
	}
public:
	union obj
	{
		union obj* listLink;//自由連結串列中指向下一個記憶體快的指標
		char clientData[1];//除錯用
	};
	static size_t GetFreeListIndex(size_t bytes)//得到所需記憶體塊在自由連結串列中的下標
	{
		return ((bytes + ALIGN - 1) / ALIGN - 1);
	}
	static size_t GetRoundUpNum(size_t bytes)//得到記憶體塊大小的向上對齊數
	{
		return (bytes + ALIGN - 1)&~(ALIGN - 1);
	}

	static void* Refill(size_t n)//從記憶體池拿出記憶體填充自由連結串列
	{
		int nobjs = 20;//申請20個n大小的記憶體塊
		char* chunk = ChunkAlloc(n, nobjs);
		if (nobj == 1)//只分配到一個記憶體
		{
			return chunk;
		}
		obj* ret = NULL;
		obj* cur = NULL;
		size_t index = GetFreeListIndex(n);
		ret = (obj*)chunk;
		cur = (obj*)(chunk + n);

		//將nobj-2個記憶體塊掛到自由連結串列上
		FreeList[index] = cur;
		for (int i = 2; i < nobjs; ++i)
		{
			cur->listLink = (obj*)(chunk + n*i);
			cur = cur->listLink;
		}
		cur->listLink = NULL;
		return ret;
	}
	static char* ChunkAlloc(size_t size, int& nobjs)
	{
		char* ret = NULL;
		size_t Leftbytes = endFree - startFree;
		size_t Needbytes = size * nobjs;
		if (Leftbytes >= Needbytes)
		{
			ret = startFree;
			startFree += Needbytes;
		}
		else if (Leftbytes >= size)//至少能分配到uoge記憶體塊
		{
			ret = startFree;
			nobjs = Leftbytes / size;
			startFree += nobjs*size;
		}
		else     //一個記憶體塊都分配不出來
		{
			if (Leftbytes > 0)
			{
				size_t index = GetFreeListIndex(Leftbytes);
				((obj*)startFree)->listLink = FreeList[index];
				FreeList[index] = (obj*)startFree;
				startFree = NULL;
			}
			//向作業系統申請2倍Needbytes加上已分配的heapsize/8的記憶體到記憶體池
			size_t getBytes = 2 * Needbytes + GetRoundUpNum(heapSize >> 4);
			startFree = (char*)malloc(getBytes);
			if (startFree == NULL)//從系統堆中分配記憶體失敗
			{
				for (int i = size; i < MAX_BYTES; i += ALIGN)
				{
					obj* head = FreeList[GetFreeListIndex(i)];
					if (head)
					{
						startFree = (char*)head;
						head = head->listLink;
						endFree = startFree + i;
						return ChunkAlloc(size, nobjs);
					}
				}
				//最後的一根救命稻草,找一級空間配置器分配記憶體
				//(其他程序歸還記憶體,呼叫自定義的控制代碼處理函式釋放記憶體)
				startFree = MallocAllocTemplate<inst>::Allocate(getBytes);
			}
			heapSize += getBytes;//從系統堆分配的總位元組數(可以用於下次分配時進行調節)
			endFree = startFree + getBytes;

			return ChunkAlloc(size, nobjs);//遞迴呼叫獲取記憶體
		}
		return ret;
	}

	static obj* volatile FreeList[FREELISTSIZE];
	static char* startFree;
	static char* endFree;
	static size_t heapSize;

};


//typename表示DefaultAllocTemplate<threads, inst>是一個型別,
//如果不標識,編譯器對此模板一無所知
template<bool threads, int inst>
typename DefaultAllocTemplate<threads, inst>::obj* volatile   
           DefaultAllocTemplate<threads, inst>::FreeList[FREELISTSIZE] = { 0 };

template<bool threads, int inst>
char* DefaultAllocTemplate<threads, inst>::startFree = 0;

template<bool threads, int inst>
char* DefaultAllocTemplate<threads, inst>::endFree = 0;

template<bool threads, int inst>
size_t DefaultAllocTemplate<threads, inst>::heapSize = 0;</span>

    這個程式碼是我自己提取出來的原始碼框架,但是他已經可以實現所有的功能。

   首先需要說明的是二級空間配置器是由一個記憶體池自由連結串列配合實現的

<span style="font-family:Microsoft YaHei;font-size:14px;">	static obj* volatile FreeList[FREELISTSIZE];//維護自由連結串列
	static char* startFree;//維護記憶體池
	static char* endFree;</span>

     srartFree就相當於水位線的一種東西,它標誌著記憶體池的大小。

     自由連結串列中其實是一個大小為16的指標陣列,間隔為8的倍數。各自管理大小分別為8,16,24,32,40,48,56,64,72,80,88,96,104, 112,120,128 位元組的小額區塊。在每個下標下掛著一個連結串列,把同樣大小的記憶體塊連結在一起。此處特別像雜湊桶。

自由連結串列結構:

<span style="font-family:Microsoft YaHei;font-size:14px;">	union obj
	{
		union obj* listLink;//自由連結串列中指向下一個記憶體快的指標
		char clientData[1];//除錯用
	};</span>

     這個結構可以看做是從一個記憶體塊中摳出4個位元組大小來,當這個記憶體塊空閒時,它儲存了下個空閒塊,當這個記憶體塊交付給使用者時,它儲存的時使用者的資料。因此,allocator中的空閒塊連結串列可以表示成:
    obj* free_list[16];

     obj* 是4個位元組那麼大,但是大部分記憶體塊大於4。我們想要做的只是將一塊塊記憶體連結起來,我們不用看到記憶體裡所有的東西,所以我們可以只用強轉為obj*就可以實現大記憶體塊的連結。

   二級空間配置器是為頻繁分配小記憶體而生的一種演算法。其實就是消除一級空間配置器的外碎片問題


作業系統頻繁分配記憶體和回收記憶體的時候。這些6M,4M的小記憶體無法利用造成了外部碎片。

二級空間配置器就比較複雜了,現在我們來分析他的那些重要的函式:

 Allocate()中:

<span style="font-family:Microsoft YaHei;font-size:14px;"><span style="white-space:pre">	</span>static size_t GetFreeListIndex(size_t bytes)//得到所需記憶體塊在自由連結串列中的下標
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>return ((bytes + ALIGN - 1) / ALIGN - 1);
<span style="white-space:pre">	</span>}</span>
    此函式和原始碼中的FREELIST_INDEX(n)是一樣的,它就是找到需要分配的記憶體塊在自由連結串列中的什麼地方,它的實現是((bytes + ALIGN - 1) / ALIGN - 1)。它其實是把藥分配的記憶體大小提升一個數量級(+7,每間隔8為一個數量級),然後除以8,可以算到要找的記憶體塊下標的下一個下標,減一,剛好久找到合適的下標處,取出一塊記憶體塊。
<span style="font-family:Microsoft YaHei;font-size:14px;">	static size_t GetRoundUpNum(size_t bytes)//得到記憶體塊大小的向上對齊數
	{
		return (bytes + ALIGN - 1)&~(ALIGN - 1);
	}</span>

      此函式是得到所需記憶體塊大小的向上對齊數。在自由連結串列中,我們的記憶體塊大小總是8的倍數,但是並不是每次所需記憶體大小都是8的倍數。所以我們就要取比所需大小大或相等的記憶體塊,這就是向上取整。&~(ALIGN - 1)相當於將低8位置0,只取高8位,高8位總是8的倍數,正好符合題意。

Allocate中最重要的兩個函式static void* Refill(size_t n)和static char* ChunkAlloc(size_t size, int& nobjs):

<span style="font-family:Microsoft YaHei;font-size:14px;">static void* Refill(size_t n)//從記憶體池拿出記憶體填充自由連結串列
	{
		int nobjs = 20;//申請20個n大小的記憶體塊
		char* chunk = ChunkAlloc(n, nobjs);
		if (nobj == 1)//只分配到一個記憶體
		{
			return chunk;
		}
		obj* ret = NULL;
		obj* cur = NULL;
		size_t index = GetFreeListIndex(n);
		ret = (obj*)chunk;
		cur = (obj*)(chunk + n);

		//將nobj-2個記憶體塊掛到自由連結串列上
		FreeList[index] = cur;
		for (int i = 2; i < nobjs; ++i)
		{
			cur->listLink = (obj*)(chunk + n*i);
			cur = cur->listLink;
		}
		cur->listLink = NULL;
		return ret;
	}</span>

     當在自由連結串列的下標處沒有記憶體塊時,我們就必須呼叫refill去填充自由連結串列。申請時一般一次性申請20個記憶體塊大小的記憶體。通過移動startFree指標將記憶體池內的一段記憶體給“切割”出來,然後按照大小切成小塊掛在自由連結串列下面。。返回第一塊記憶體塊給使用者,其餘的都掛在自由連結串列下,方便下次分配,根據區域性性原理,這將極大地提升了分配記憶體空間的效率
<span style="font-family:Microsoft YaHei;font-size:14px;">static char* ChunkAlloc(size_t size, int& nobjs)
	{
		char* ret = NULL;
		size_t Leftbytes = endFree - startFree;
		size_t Needbytes = size * nobjs;
		if (Leftbytes >= Needbytes)
		{
			ret = startFree;
			startFree += Needbytes;
		}
		else if (Leftbytes >= size)//至少能分配到一個記憶體塊
		{
			ret = startFree;
			nobjs = Leftbytes / size;
			startFree += nobjs*size;
		}
		else     //一個記憶體塊都分配不出來
		{
			if (Leftbytes > 0)
			{
				size_t index = GetFreeListIndex(Leftbytes);
				((obj*)startFree)->listLink = FreeList[index];
				FreeList[index] = (obj*)startFree;
				startFree = NULL;
			}
			//向作業系統申請2倍Needbytes加上已分配的heapsize/8的記憶體到記憶體池
			size_t getBytes = 2 * Needbytes + GetRoundUpNum(heapSize >> 4);
			startFree = (char*)malloc(getBytes);
			if (startFree == NULL)//從系統堆中分配記憶體失敗
			{
				for (int i = size; i < MAX_BYTES; i += ALIGN)
				{
					obj* head = FreeList[GetFreeListIndex(i)];
					if (head)
					{
						startFree = (char*)head;
						head = head->listLink;
						endFree = startFree + i;
						return ChunkAlloc(size, nobjs);
					}
				}
				//最後的一根救命稻草,找一級空間配置器分配記憶體
				//(其他程序歸還記憶體,呼叫自定義的控制代碼處理函式釋放記憶體)
				startFree = MallocAllocTemplate<inst>::Allocate(getBytes);
			}
			heapSize += getBytes;//從系統堆分配的總位元組數(可以用於下次分配時進行調節)
			endFree = startFree + getBytes;

			return ChunkAlloc(size, nobjs);//遞迴呼叫獲取記憶體
		}
		return ret;
	}</span>

ChunkAlloc要做的就是去找作業系統要記憶體,依次性要20個,但是我們要考慮很多情況:

  1. 記憶體池裡有足夠20塊大的記憶體
  2. 記憶體池裡有小於20塊大於等於1塊的記憶體大小
  3. 記憶體池裡1塊記憶體那麼大都沒有
STL是這樣做的:     如果有足夠的記憶體,那麼一次性就給20塊,返回第一塊給使用者,其餘的掛在自由連結串列上。                                只有一塊或者多塊,返回一塊給使用者。                                沒有記憶體了,找作業系統要。                                作業系統沒有了,啟用最後一根救命稻草,呼叫一級空間配置器,通過控制代碼函式釋放記憶體,分配記憶體。 這個就是二級空間配置器的主要邏輯結構。 還有要說明的幾點就是:
  1. 空間配置器裡所有的成員都是靜態的。是為了在外面通過作用域就可以呼叫,而不需要構造物件。
  2. 空間配置器可以使用於大部分的資料結構,如List,vector等。
  3. 對於自由連結串列的初始化時特別容易錯的。
    template<bool threads, int inst>
    typename DefaultAllocTemplate<threads, inst>::obj* volatile  
            DefaultAllocTemplate<threads, inst>::FreeList[FREELISTSIZE] = { 0 };
    注意到typename了嗎。它就為了完成一個功能,到蘇編譯器DefaultAllocTemplate<threads, inst>是一個型別,不然會出現如下錯誤:



這是難以發現的錯誤,編譯器認識DefaultAllocTemplate<threads, inst>,報一個搞不懂的錯誤。

相關推薦

STL-空間配置剖析

         網上有很多對於STL空間配置器原始碼的剖析,之所以這麼多人去剖析空間配置器,我覺得是真的設計的太好,而且剖析空間配置器的架構的設計對於C++學者來說是一個不錯的提高能力的專案,所以加入到這個解剖大軍中來。       參照了侯捷的《STL原始碼剖析》,原本

STL空間配置剖析

根據情況來判定,如果配置區塊大於128bytes,說明“足夠大”,呼叫第一級配置器,而小於等於128bytes,則採用複雜記憶體池(memory pool)來管理。template <bool threads, int inst> class __default_alloc_template

SGI STL空間配置STL原始碼剖析

空間配置器的標準介面(根據STL規範) allocator::value_typeallocator::pointerallocator::const_pointerallocator::referenceallocator::const_referencealloca

[SGI STL]空間配置--記憶體管理

[SGI STL]系列文章前言        廢話不多說,讀侯捷的SGI STL原始碼分析目的有三個: 1,接觸c++不久就開始跟STL打交道,一直有個好奇心,這麼強大的庫到底是誰、咋實現的?; 2,不熟悉實現就用不好STL,所以想更好的應用STL,就有必要一探其底層驅

STL空間配置

零、為何STL要單獨設計空間配置器? 一開始我有過這樣的疑惑:為什麼STL不直接使用malloc和free操縱記憶體即可,為什麼還要設計空間配置器呢?這不是多此一舉嗎?後來在學習之後才明白這樣做是為了進一步提高記憶體的使用率和使用效率。主要是從以下兩方面來考慮的: 1.小

STL空間配置allocator詳解

stl六大元件簡介 我們知道,stl有容器,空間配置器,介面卡,迭代器,仿函式以及演算法這6個元件,它們六者關係大概如下:容器通過配置器取得資料儲存空間,演算法通過迭代器獲取容器內容,仿函式可以協助演算法完成不同的策略變化,配接器可以修飾或套界仿函式。 侯捷在《STL原始

stl空間配置簡介

  1、 符合STL標準的空間配器介面 STL是c++中使用非常廣泛的一個標準庫,它包含各種有用的容器。而空間配置器作為STL各種容器的背後的核心,負責容器內部記憶體的分配和釋放。不過空間配置器可以分配的也不只是記憶體,因為空間也意味著可以是磁碟或者其他儲存介質。下邊是一個符合STL規範的空間配置器的必要介

STL 空間配置 allocator

STL的操作物件(所有的數值)都存放在容器之中,而容器則需要配置空間以置放資料。最近在看侯捷的《STL原始碼剖析》,所以做了筆記。 為什麼不說allocator是記憶體配置器而說他是空間配置器呢? 因為空間不一定是記憶體,空間也可以是磁碟或其他輔助儲存介質

SGI STL空間配置-第一級空間配置

一、SGI STL配置器簡介 如果要了解STL的實現,必須要了解空間配置器,因為整個STL的操作物件都放在容器之內,而容器一定需要配置空間以存放資料等資料。allocator叫做空間配置器而不是記憶體配置器,因為空間不一定是記憶體,也可以是磁碟或者其他

STL——空間配置

STL有6大元件:容器、演算法、迭代器、仿函式、配接器、分配器。它們之間的密切關係是STL的精髓所在,容器用來存放資料,而容器存在的前提是要有分配器給它分配記憶體,接下來需要實現演算法,迭代器便作為演算法來對容器資料操作的橋樑,演算法可以使用仿函式完成不同的策略

STL空間配置-第一級配置

一、SGI STL配置器簡介 SGI STL的配置器與眾不同,它與標準規範不同。如果要在程式中明確使用SGI配置器,那麼應該這樣寫: vector<int,std::alloc>iv; 他的名字是alloc,而且不接受任何引數。標準配置器的名字是allocator,而且可以接受引數。

STL空間配置、vector、list、deque、map復習

管理 其他 過程 prev 得到 大於 新元素 use 總量 本文寫於2017-03-03,從老賬號遷移到本賬號,原文地址:https://www.cnblogs.com/huangweiyang/p/6440830.html STL的六大組件:容器、算法、叠代器、空間配置

STL深入學習】SGI STL空間配置詳解(二)-第二級空間配置

本文講解SGI STL空間配置器的第二級配置器。 相比第一級配置器,第二級配置器多了一些機制,避免小額區塊造成記憶體的碎片。不僅僅是碎片的問題,配置時的額外負擔也是一個大問題。因為區塊越小,額外負擔所佔的比例就越大。 額外負擔是指動態分配記憶體塊的時候,位於其頭部的額外資訊

[C++]STL-空間配置(一)

空間配置器 從STL的實現來說,首先需要明白的就是空間配置器,因為整個STL的操作物件都放在容器中,而容器需要一定配置空間以置放資料。 空間配置器的標準介面 // 標準介面,一些typedef allocator::value_typ

C++STL 空間配置allocator

先來介紹一下STL的六大元件1. 空間配置器:記憶體池實現小塊記憶體分配,對應到設計模式--單例模式(工具類,提供服務,一個程式只需要一個空間配置器即可),享元模式(小塊記憶體統一由記憶體池進行管理)2.迭代器:迭代器模式,模板方法3.容器:STL的核心之一,其他元件圍繞容器

STL-空間配置、迭代、traits程式設計技巧

目錄 記憶體分配和釋放 物件的構造和析構 traits要解決的問題 內嵌類別宣告解決非指標迭代器的情況 使用模板特例化解決普通指標的情況 迭代器相應類別

STL原始碼剖析(二)空間配置

歡迎大家來訪二笙的小房子,一同學習分享生活! 文章目錄 1. 寫在前面 2. SGI空間配置器 2.1 SGI標準空間配置器 2.2 SGI特殊的空間配置器,std::alloc 2.3 構造和析構基本工具 2.4 空間

C++標準庫——STL空間配置

但是 chunk 內容 既然 部分 如何 標識 stl源碼 strong 聲明:源碼同《STL源碼剖析》(侯捷) STL:   C++標準的模板庫,通用性高。   常見的數據結構封裝。   提供常用的通用算法。 STL六大組件:   容器 算法 叠

STL原始碼分析之空間配置

前言 SGI STL將new的申請空間和呼叫建構函式的兩個功能分開實現, 如果對new不太清楚的, 可以先去看看這一篇new實現再來看配置器也不遲. 本節是STL分析的第一篇, 主要分析STL各個部分都會出現的alloc實現, 雖然每個部分都只會預設呼叫它, 不瞭解它也可以看懂分析,

STL學習筆記(1)空間配置 allocator

1 簡述     STL其他元件都是存放在空間配置器配置的空間中,此處空間可以是記憶體,也可以是磁碟或其他輔助儲存介質。     allocator負責記憶體的分配和釋放,以及負責物件的構造和析構,兩個操作時分開的。     每個容器都已經制定了預設的空間配置器