C++ 頭文件系列(string)----分析string初始化內存模型


測大小

這里我們比較4種版本的basic_string模版類,分別是:string, wstring, u16string, u32string. 雖然他們是不同的字符串類型,但是其sizeof的結果卻一樣,都為40字節(x64下):

sizeof-image

看源碼

我們都知道,上面4個不同的類型是同一份模版(basic_string)的實例化,因此它們的內存模型都是相同的。 這里我們來追蹤一下string類型的源代碼,源碼引用VS2013版的標准string庫。

看繼承

看得出,basic_string的繼承體系非常復雜(當前無關部分我用...代替了)。

1. typedef basic_string<char, char_traits<char>, allocator<char> >
	string;
				↓↓↓
2. class basic_string
	: public _String_alloc<!is_empty<_Alloc>::value,
		_String_base_types<_Elem, _Alloc> > {...}
				↓↓↓
3. class _String_alloc
	: public _String_val<typename _Alloc_types::_Val_types> {...}
				↓↓↓
4. class _String_val
	: public _Container_base {...}
				↓↓↓
5. typedef _Container_base12 _Container_base;
				↓↓↓
6. struct _Container_base12 {...}

看成員

光有繼承體系還不夠,我們還得看看類成員。 注意,這里不需要關心模版參數,至於為什么,你們自己好好想想嘍 >-<)

members-image

看定義

能夠看到,_Container_base12類只包含一個指針(指向一個代理類,這里我們不深究),大小永遠為1個字長。 因此,我們主要來看看_String_val類的成員定義:

1. enum
	 {	// length of internal buffer, [1, 16]
	  _BUF_SIZE = 16 / sizeof (value_type) < 1 ? 1
		 : 16 / sizeof (value_type)};

  union _Bxty
	{	// storage for small buffer or pointer to larger one
	value_type _Buf[_BUF_SIZE];
	pointer _Ptr;
	char _Alias[_BUF_SIZE];	// to permit aliasing
	} _Bx;

2. size_type _Mysize;	// current length of string
3. size_type _Myres;	// current storage reserved for string

其中,_BUF_SIZE定義了緩沖區的長度:

  • 若value_type類型小於1字節,則 _BUF_SIZE = 16
  • 否則,_BUF_SIZE = 16 / sizeof(value_type)。(留心,這里是整除取商!!!)

析類型

這里有幾個類型定義非常重要:value_type, pointer, size_type。 從源代碼上看,這些類型經過了一層又一層的typedef,源頭難辨。 因此,我們轉而從標准草案來先解讀value_type

typedef typename traits::char_type		value_type;

X::char_type	->		charT
charT			->		char

其它兩個類型也依理分析,最后得出它們的實際類型分別為:

types-image

得結果

綜上,字符串類型內存模型如下:

memory-model-image

最后讓我們拿string類型來驗證一下(><良心保證,下圖為代碼運行結果,非純數字打印):

check-image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM