1. 程式人生 > >STL原始碼剖析之stl_alloc(一)

STL原始碼剖析之stl_alloc(一)

STL主要研究的六大問題:空間配置器,迭代器,容器,仿函式,演算法,容器介面卡

一級空間配置器原始碼如下:

#if 0
#include<new>
#define __THROW_BAD_ALLOC throw bad_alloc
#else
#include<iostream.h>
#include<malloc.h>
#include<stdlib.h>
#define __THROW_BAD_ALLOC cerr<<"Out Of Memory."<<endl;exit(1)
#endif

//malloc  free

template<int inst>
class __malloc_alloc_template
{
private:
	//以下都是函式指標,所代表的函式將用來處理記憶體不足的情況。
	static void* oom_malloc(size_t n)
	{
		void (*my_malloc_handler)();
		void *result;
		for(;;) //不斷嘗試釋放、配置、再釋放、再配置…
		{
			my_malloc_handler = __malloc_alloc_oom_handler;
			if(0 == my_malloc_handler)
			{
				__THROW_BAD_ALLOC;
			}
			(*my_malloc_handler)();//呼叫處理例程,企圖釋放記憶體。
			result = malloc(n);//再次嘗試配置記憶體。
			if(result)
				return result;
		}
	}
	static void* oom_realloc(void *p, size_t n)
	{
		void (* my_malloc_handler)();
		void *result;
		for (;;) //不斷嘗試釋放、配置、再釋放、再配置…
		{
			my_malloc_handler = __malloc_alloc_oom_handler;
			if (0 == my_malloc_handler) 
			{
				__THROW_BAD_ALLOC; 
			}
			(*my_malloc_handler)();//呼叫處理例程,企圖釋放記憶體。
			result = realloc(p, n);//再次嘗試配置記憶體。
			if (result) 
				return(result);
		}
	}
	static void(*__malloc_alloc_oom_handler)();
public:
	static void* allocate(size_t n)
	{
		void *result = malloc(n);
		//第一級配置器直接使用 malloc()
		//以下,無法滿足需求時,改用 oom_malloc()
		if(0 == result)
			result = oom_malloc(n);
		return result;
	}
	static void  deallocate(void *p, size_t n)
	{
		free(p);//第一級配置器直接使用 free()
	}
	static void* reallocate(void *p, size_t old_sz, size_t new_sz)
	{
		void *result = realloc(p, new_sz);
		//第一級配置器直接使用 realloc()
		//以下,無法滿足需求時,改用 oom_realloc()
		if(0 == result)
			result = oom_realloc(p, new_sz);
		return result;
	}
public:
	//set_new_handler模擬,可用透過它指定你自己的out_of_memory handler
	static void(*set_malloc_handler(void(*f)()))()
	{
		void(*old)() = __malloc_alloc_oom_handler;
		__malloc_alloc_oom_handler = f;
		return old;
	}
};
// malloc_alloc  out-of-memory handling
//初值為 0。有待客端設定。
void(* __malloc_alloc_template<0>::__malloc_alloc_oom_handler)() = 0;

typedef __malloc_alloc_template<0> malloc_alloc;

第一級配置器以 malloc(), free(), realloc() 等 C函式執行實際的記憶體配置、釋放、重配置動作,並實作出類似 C++ new-handler7 的機制。它不能直接運用 C++ new-handler機制,因為它並非使用 ::operatornew 來配置記憶體。所謂 C++ new handler 機制是,你可以要求系統在記憶體配置需求無法被滿足時,喚起一個你所指定的函式。換句話說一旦 ::operator new 無法達成任務,在丟出std::bad_alloc異常狀態之前,會先呼叫由客端指定的處理例程。此處理例程通常即被稱為 new-handler。new-handler 解決記憶體不足的作法有特定的模式,請參考《Effective C++》2e 條款 7。
注意,SGI 以 malloc  而非 ::operator new 來配置記憶體(我所能夠想象的一個原因是歷史因素,另一個原因是 C++並未提供相應於 realloc() 的記憶體配置動作),因此 SGI 不能直接使用 C++的 set_new_handler() ,必須模擬一個類似的 set_malloc_handler() 。
請注意,SGI 第一級配置器的 allocate()  和 realloc() 都是在呼叫 malloc()和 realloc() 不成功後,改呼叫 oom_malloc() 和oom_realloc() 。後兩者都有內迴圈,不斷呼叫「記憶體不足處理例程」,期望在某次呼叫之後,獲得足夠的記憶體而圓滿達成任務。但如果「記憶體不足處理例程」並未被客端設定,oom_malloc() 和 oom_realloc()  便老實不客氣地呼叫 __THROW_BAD_ALLOC ,
丟出bad_alloc異常訊息,或利用 exit(1) 硬生生中止程式。記住,設計「記憶體不足處理例程」是客端的責任,設定「記憶體不足處理例程」也是客端的責任。再一次提醒你,「記憶體不足處理例程」解決問題的作法有著特定的模式,請參考 [Meyers98]條款 7。

二級空間配置器原始碼:

enum {__ALIGN = 8}; //小型區塊的上調邊界
enum {__MAX_BYTES = 128}; //小型區塊的上限
enum {__NFREELISTS = __MAX_BYTES / __ALIGN};// free-list s個數

//以下是第二級配置器。
//注意,無「template 型別引數」,且第二引數完全沒派上用場。
//第一引數用於多緒環境下。本書不討論多緒環境。

template<bool threads, int inst>
class __default_alloc_template
{
public:
	static void * allocate(size_t n);
	static void   deallocate(void *p, size_t n);
	static void * reallocate(void *p, size_t old_sz, size_t new_sz);
protected:
	static void * refill(size_t n);
	static char* chunk_alloc(size_t size, int &nobjs);
private:
	// ROUND_UP()  將 bytes上調至 8的倍數。
	static size_t ROUND_UP(size_t bytes)
	{
		return ((bytes + __ALIGN-1) &~(__ALIGN-1));
	}
private:
	union obj  // free-list s 的節點構造
	{
		union obj * free_list_link;
		char client_data[1];
	};
private:
	// 以下函式根據區塊大小,決定使用第 n號  free-list 。n 從 1 起算。
	static size_t  FREELIST_INDEX(size_t bytes)
	{
		return ((bytes + __ALIGN-1) / __ALIGN-1);
	}
	static obj* free_list[__NFREELISTS];
private:
	static char * start_free;
	static char * end_free;
	static size_t heap_size;
};
//以下是 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*
__default_alloc_template<threads, inst>::free_list[__NFREELISTS] = 
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

template<bool threads, int inst>
void * __default_alloc_template<threads, inst>::allocate(size_t n)
{
	obj ** my_free_list;
	obj * result;
	if(n > __MAX_BYTES)
		return malloc_alloc::allocate(n);
	
	my_free_list = free_list + FREELIST_INDEX(n);
	result = *my_free_list;
	if(result == 0)
	{
		void *r = refill(ROUND_UP(n));
		return r;
	}
	*my_free_list = result->free_list_link;
	return result;
}
/*記憶池(memory pool)*/
//假設 size  已經適當上調至 8的倍數。
//注意引數 nobjs是 pass by reference 。
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;
    size_t bytes_left = end_free - start_free;// 記憶池剩餘空間
	
    if (bytes_left >= total_bytes) 
	{
		// 記憶池剩餘空間完全滿足需求量。
        result = start_free;
        start_free += total_bytes;
        return(result);
    } 
	else if (bytes_left >= size) 
	{	
		// 記憶池剩餘空間不能完全滿足需求量,但足夠供應一個(含)以上的區塊。
        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) {
			// 記憶池內還有一些零頭,先配給適當的  free list 。
			// 首先尋找適當的  free list 。
			obj * volatile * my_free_list =
				free_list + FREELIST_INDEX(bytes_left);
			// 調整  free list ,將記憶池中的殘餘空間編入。
			((obj *)start_free) -> free_list_link = *my_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;
			// 試著檢視我們手上擁有的東西。這不會造成傷害。我們不打算嘗試配置
			//  較小的區塊,因為那在多行程( multi-process )機器上容易導致災難
			// 以下搜尋適當的  free list ,
			//  所謂適當是指「尚有未用區塊,且區塊夠大」之  free list 。
			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;
					// 遞迴呼叫自己,為了修正 nobjs。
					return( chunk_alloc (size, nobjs));
					// 注意,任何殘餘零頭終將被編入適當的  free-list 中備用。
				}
			}
			end_free = 0;  // 如果出現意外(山窮水盡,到處都沒記憶體可用了)
			// 呼叫第一級配置器,看看 out-of-memory 機制能否盡點力
			start_free = (char *)malloc_alloc::allocate(bytes_to_get);
			// 這會導致擲出異常(exception),或記憶體不足的情況獲得改善
			}
		heap_size += bytes_to_get;
			end_free = start_free + bytes_to_get;
		//  遞迴呼叫自己,為了修正 nobjs。
			return(chunk_alloc(size, nobjs));
		}
	}
	
	
	
	
	//傳回一個大小為 n的物件,並且有時候會為適當的 freelist 增加節點.
	//假設 n已經適當上調至 8的倍數。
	template <bool threads, int inst>
		void* __default_alloc_template<threads, inst>::refill(size_t n)
	{
		int nobjs = 20;
		// 呼叫 chunk_alloc() ,嘗試取得 nobjs個區塊做為  free list 的新節點。
		// 注意引數 nobjs是 pass by reference 。
		char * chunk = chunk_alloc(n, nobjs);
		obj ** 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空間內建立 freelist
		result = (obj *)chunk;//這一塊準備傳回給客端
		// 以下導引  free list 指向新配置的空間(取自記憶池)
		*my_free_list = next_obj = (obj *)(chunk + n);
		// 以下將  free list  的各節點串接起來。
		for (i = 1; ; i++)  //從 1 開始,因為第 0 個將傳回給客端
		{	
			current_obj = next_obj;
			next_obj = (obj *)((char *)next_obj + n);
			if (nobjs - 1 == i) 
			{
				current_obj -> free_list_link = 0;
				break;
			} 
			else 
			{
				current_obj -> free_list_link = next_obj;
			}
		}
		return(result);
	}
	
	template <bool threads, int inst>
		void*
		__default_alloc_template<threads, inst>::reallocate(void *p,
		size_t old_sz,
		size_t new_sz)
	{
		void * result;
		size_t copy_sz;
		
		if (old_sz > (size_t) __MAX_BYTES && new_sz > (size_t) __MAX_BYTES) 
		{
			return(realloc(p, new_sz));
		}
		if (ROUND_UP(old_sz) == ROUND_UP(new_sz))
			return(p);
		result = allocate(new_sz);
		copy_sz = new_sz > old_sz? old_sz : new_sz;
		memcpy(result, p, copy_sz);
		deallocate(p, old_sz);
		return(result);
	}
	
	
	template <bool threads, int inst>
		void __default_alloc_template<threads, inst>::deallocate(void *p, size_t n)
	{
		obj *q = (obj *)p;
		obj ** my_free_list;
		if (n > (size_t) __MAX_BYTES) 
		{
			malloc_alloc::deallocate(p, n);
			return;
		}
		my_free_list = free_list + FREELIST_INDEX(n);
		q -> free_list_link = *my_free_list;
		*my_free_list = q;
	}
	
	/////////////////////////////////////////////////////////////////
	
#ifdef __USE_MALLOC
	typedef __malloc_alloc_template<0> malloc_alloc;
	typedef malloc_alloc alloc;
#else
	typedef __default_alloc_template<0,0> alloc;
#endif
	
	template<class T, class Alloc>
		class simple_alloc
	{
public:
	static T * allocate(size_t n)
	{
		return 0==n ? 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));
	}
	};

第二級配置器多了一些機制,避免太多小額區塊造成記憶體的破碎。小額區塊帶來的其實不僅是記憶體破碎而已,配置時的額外負擔(overhead)也是一大問題 8 。額外負擔永遠無法避免,畢竟系統要靠這多出來的空間來管理記憶體,
但是區塊愈小,額外負擔所佔的比例就愈大、愈顯得浪費。
SGI第二級配置器的作法是,如果區塊夠大,超過 128 bytes,就移交第一級配置器處理。當區塊小於 128 bytes,則以記憶池(memory pool)管理,此法又稱為次層配置(sub-allocation):每次配置一大塊記憶體,並維護對應之自由序列(free-
list)。下次若再有相同大小的記憶體需求,就直接從free-lists中撥出。如果客端釋還小額區塊,就由配置器回收到free-lists中—是的,別忘了,配置器除了負責配置,也負責回收。為了方便管理,SGI第二級配置器會主動將任何小額區塊的記憶體需求量上調至8的倍數(例如客端要求 30 bytes,就自動調整為 32bytes),並維護 16 個 free-lists,各自管理大小分別為 8, 16, 24, 32, 40, 48, 56, 64, 72,80, 88, 96, 104, 112, 120, 128 bytes的小額區塊。free-lists 的節點結構如下:
union obj {
union  obj * free_list_link;
char client_data[1]; /* The client sees this. */
};
可能我們會想為了維護序列(lists),每個節點需要額外的指標(指向下一個節點),這不又造成另一種額外負擔嗎?你的顧慮是對的,但早已有好的解決辦法。注意,上述 obj 所用的是 union ,由於 union 之故,從其第一欄位觀之, obj 可被視為一個指標,指向相同形式的另一個 obj 。從其第二欄位觀之, obj 可被視為一個指標,指向實際區塊,如圖2-4。一物二用的結果是,不會為了維護序列所必須的指標而造成記憶體的另一種浪費(我們正在努力樽節記憶體的開銷呢)。
這種技巧在強型(strongly typed)語言如 Java 中行不通,但是在非強型語言如 C++中十分普遍 。free-list 這是一個小額區塊這些區塊已交給客端使用,所以 free-list不再指向它們。
 

上述的  chunk_alloc() 函式以 end_free - start_free  來判斷記憶池的水量。如果水量充足,就直接撥出 20 個區塊傳回給 free list。如果水量不足以提供 20 個區塊,但還足夠供應一個以上的區塊,就撥出這不足20個區塊的空間出去。這時
候其pass by reference 的  nobjs  引數將被修改為實際能夠供應的區塊數。如果記憶池連一個區塊空間都無法供應,對客端顯然無法交待,此時便需利用 malloc()從 heap 中配置記憶體,為記憶池注入活水源頭以應付需求。新水量的大小為需求
量的兩倍,再加上一個隨著配置次數增加而愈來愈大的附加量。
舉個例子,假設程式一開始,客端就呼叫 chunk_alloc(32,20) ,於是malloc() 配置 40個 32bytes區塊,其中第 1 個交出,另 19 個交給 free_list[3]維 護 , 餘20 個 留 給 記 憶 池 。 接 下 來 客 端 呼 叫 chunk_alloc(64,20) , 此 時free_list[7]  空空如也,必須向記憶池要求支援。記憶池只夠供應 (32*20)/64=10個 64bytes區塊,就把這 10 個區塊傳回,第 1 個交給客端,餘 9個由  free_list[7]維護。此時記憶池全空。接下來再呼叫 chunk_alloc(96, 20) ,此時  free_list[11]空空如也,必須向記憶池要求支援,而記憶池此時也是空的,於是以 malloc() 配置 40+n(附加量)個 96bytes 區塊,其中第 1 個交出,另 19 個交給  free_list[11]維護,餘 20+n(附加量)個區塊留給記憶池……。萬一山窮水盡,整個system heap 空間都不夠了(以至無法為記憶池注入活水源頭), malloc() 行動失敗, chunk_alloc() 就㆕處尋找有無「尚有未用區塊,且區塊夠大」之free lists。找到的話就挖一塊交出,找不到的話就呼叫第一級配置器。第一級配置器其實也是使用 malloc() 來配置記憶體,但它有 out-of-memory處理機制(類似 new-handler 機制),或許有機會釋放其它的記憶體拿來此處使用。如果可以,就成功,否則發出bad_alloc異常。
以上便是整個第二級空間配置器的設計。

補充內容:

容器:序列式容器,關聯式容器

序列式容器(Sequence Contiainers):array(build-in),vector,heap,priority-queue,list,slist,deque,stack,queue

關聯式容器(Associative Containers):RB-tree,set,map,multiset,multimap,hashtablke,hash_set,hash_map,hash_multiset,hash_multimap

一. malloc calloc realloc _alloca free ; new detele

  1. 靜態申請在堆區,Test t; 動態申請在棧區,ps:     Test *pt = malloc(sizeof(Test)); pt->fun(); 空類大小是1 ; //在申請空間時候呼叫了構造  

  2. c語言中maclloc在呼叫時要強轉而且計算開闢大小,而且在程式結束時要進行手動 釋放,而且在釋放前要析構物件 。 c++則用new detele 代替了。new申請空間,構造物件;deletel析構物件,釋放空間。

  3. new,operator new, new operator , placement new

            new 和detele 可以進行過載,

operator new  原型為  void * operator new(sizt_t *) //無符號整型

placement new呼叫格式: new(p)int(10); //在原有的空間上構造一個物件進行賦值,預設構造在第一個空間上,定位可以進行控制需要過載new

void* operator new(sizt_t sz , int *ptr,int pos)

{

return &ptr[pos];  //進行第幾個空間進行賦值 ps: new(p)[

}

allocator.construct(&_Acc:_Value(_S),_X) // 具有通用性

//深拷貝,淺拷貝 預設情況按成員賦值

二.stl中的空間配置器

SGI_STL

#include<stl_alloc.h>

1.向堆區申請 2.多執行緒 3.記憶體不足時候的應變 4.小型區塊造成的記憶體碎片問題

一級空間配置器是 128k以內 

   set_new_handler c++才有;c 沒有

 思考: 2^32 /4 申請不了空間 再處於2  可以申請 ???

針對申請記憶體空間,set_new_handler()是一個回撥函式, // 回撥函式 , 預防記憶體申請不成功 這是一個死迴圈函式 ,內部存在while(1).

參考文獻:《STL原始碼剖析》

相關推薦

STL原始碼剖析stl_alloc()

STL主要研究的六大問題:空間配置器,迭代器,容器,仿函式,演算法,容器介面卡 一級空間配置器原始碼如下: #if 0 #include<new> #define __THROW_BAD_ALLOC throw bad_alloc #else #include

STL原始碼剖析map和set

之前分析二叉搜尋樹和平衡二叉樹時,真心感覺樹的實現真是難,特別是平衡二叉樹,不平衡之後需要調整,還要考慮各種情況,累感不愛.今天看到這個紅黑樹,發現比平衡二叉樹還難,但是紅黑樹比平衡二叉樹使用的場景更多,所以平常使用時,我們需要了解紅黑樹的實現原理,如果有能力,可以自己實現,但是如果實在做不出來,也

STL原始碼剖析雜湊表 hashtable

雜湊表,一種鍵值對用的關係。具有關聯性。 也稱散列表,主要是通過特殊演算法建立值和鍵的關係,然後根據鍵值對應儲存和搜尋。 因為是鍵值對應的關係,所以再鍵的儲存上面,會出現一種【碰撞】問題,即根據演算法計算兩個不同的值對應了同一個鍵,因為導致鍵的儲存衝突。 雜湊表根據解決【碰撞】的方案不

STL原始碼剖析stl_deque的實現(二)

STL中deque(雙端佇列)是一種非常重要的結構,stack,與queue底層都是藉助deque. deque(雙端佇列)是一種雙向開口的連續性空間,雙向開口意思是可以在頭尾兩端做元素的插入和刪除操作。deque和vector最大的差異在於deque允許常數時間內對起頭端

STL原始碼剖析

歡迎大家來訪二笙的小房子,一同學習分享生活! 寫在前面 學習STL,瞭解STL的歷史與發展,深度剖析STL原始碼,提高自己的程式設計能力!!! 1.瞭解STL 1.1 STL概述 STL誕生:為了建立資料結構和演算法的一套標準,並且降低其間的耦合關係以提

java原始碼剖析socket(

    不知不覺又到了新的的一週,時間在悄悄的溜走,所辛的是自己也在緩慢的推進著自己的學習計劃。      這周按照計劃檢視的是socket系列的相關類,儘管這之前就已經看過一遍,不過當時是越看越蒙,完全找不到北。 隨著自己能力的提升,回過頭來又去看一遍,還是看不懂其中的精

STL原始碼剖析》學習迭代器

一、迭代器作用        在設計模式中有一種模式叫迭代器模式,簡單來說就是提供一種方法,在不需要暴露某個容器的內部表現形式情況下,使之能依次訪問該容器中的各個元素,這種設計思維在STL中得到了廣泛的應用,是STL的關鍵所在,通過迭代器,容器和演算法可以有機的粘合在一

C++ STL原始碼剖析——stl_alloc.h

stl_alloc.h # // Comment By: 凝霜 # // E-mail: [email protected] # // Blog: http://blog.csdn.net/mdl13412 # # //

STL原始碼剖析》——迭代器(iterators)概念與traits程式設計技法(

一、迭代器設計思維——STL關鍵所在         STL的中心思想在於:將資料容器(containers)和演算法(algorithms)分開,彼此獨立設計,最後再以一帖粘合劑將它們撮合在一起。 二、迭代器(iterator)是一種 smart pointer    

STL原始碼剖析——STL演算法find查詢演算法

前言     由於在前文的《STL演算法剖析》中,原始碼剖析非常多,不方便學習,也不方便以後複習,這裡把這些演算法進行歸類,對他們單獨的原始碼剖析進行講解。本文介紹的STL演算法中的find、search查詢演算法。在STL原始碼中有關演算法的函式大部分在本文介紹,包含fi

Android框架原始碼解析)Volley

前幾天面試CVTE,HR面掛了。讓內部一個學長幫我查看了一下面試官評價,發現二面面試官的評價如下: 廣度OK,但缺乏深究能力,深度與實踐不足 原始碼:只能說流程,細節程式碼不清楚,retrofit和volley都是。 感覺自己一方面:自己面試技巧有待提高吧(框

STL原始碼剖析——stack的實現原理和使用方法詳解

Stack 簡介     stack 是堆疊容器,是一種“先進後出”的容器。     stack 是簡單地裝飾 deque 容器而成為另外一種容器。     使用 stack 時需要加上標頭檔案 #include<s

STL原始碼剖析——deque的實現原理和使用方法詳解

Deque 簡介     deque是“double—ended queue”的縮寫,和vector一樣都是STL的容器,deque 是雙端陣列,而 vector 是單端的。     deque 在介面上和 vector 非常相似,在許多操作的地方

STL原始碼剖析——序列式容器

序列式容器 所謂序列化容器,其中的元素都可序,但未必有序。C++語言本省提供了一個序列式容器array,STL另外提供了vector,list,deque,stack,queue,priority_queue等序列式容器。其中stack和queue由於只是將deque作為底層

STL原始碼剖析——list容器的排序演算法sort()

原文:https://blog.csdn.net/chenhanzhun/article/details/39337331 前言     由於STL本身的排序演算法sort接受的輸入迭代器是隨機訪問迭代器,但是雙向list連結串列容器的訪問方式是雙向迭代器,因此,不能使用

SNMP原始碼分析)配置檔案部分

snmpd.conf想必不陌生。在程序啟動過程中會去讀取配置檔案中各個配置。其中幾個引數需要先知道是幹什麼的:   token:配置檔案的每行的開頭,例如 group MyROGroup v1 readSec 這行token的引數是group。  

STL原始碼剖析(三)迭代器與traits程式設計

文章目錄 1. 迭代器概念 1.1 基本概念 1.2 迭代器設計理念 2. 引出traits程式設計 3. traits程式設計 3.1 traits程式設計技術 3.2 partial special

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

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

STL原始碼剖析(五)【hash_set、hash_map】

hash_set 與set區別及聯絡 與set大同小異,set以RB-tree作為其底層,而hash_set以hash table作為其底層 兩者都是藉由其底層操作完成我們所看到的那些操作 二者最大的不同在於set的底層RB-tree有自動排序功能,所以反映在se

STL原始碼剖析(五)hashtable

文章目錄 1. hashtable概述 1.1 線性探測 1.2 二次探測 1.3 開鏈法 2. hashtable的桶與節點 3. hashtable迭代器 4. hashtable資料結構 5. has