www.888000ff.comC++ 头文件序列(string)—-分析string初阶化内存模型

测大小

此处我们相比4种版本的basic_string模版类,分别是:string, wstring,
u16string, u32string.
就算她们是见仁见智的字符串类型,然而其sizeof的结果却一样,都为40字节(x64下):

www.888000ff.com 1

测大小

此处我们相比较4种版本的basic_string模版类,分别是:string, wstring,
u16string, u32string.
即使她们是例外的字符串类型,但是其sizeof的结果却一样,都为40字节(x64下):

www.888000ff.com 2

看源码

咱们都晓得,上边4个例外的品类是一律份模版(basic_string)的实例化,由此它们的内存模型都是平等的
这里我们来追踪一下string类型的源代码,源码引用VS2013版的正规string库。

看源码

咱俩都知道,下边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 {...}

看继承

看得出,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 {...}

看成员

光有继承系列还不够,我们还得看看类成员。
注意,这里不需要关爱模版参数,至于怎么,你们自己优秀想想喽
>-<)

www.888000ff.com 3

看成员

光有继承系列还不够,大家还得看看类成员。
注意,这里不需要关怀模版参数,至于为什么,你们自己完美想想喽
>-<)

www.888000ff.com 4

看定义

能够看出,_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)**。(留心,这里是整除取商!!!)

看定义

可以看出,_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

任何五个门类也依理分析,末了得出它们的实在类型分别为:

www.888000ff.com 5

析类型

那边有多少个类型定义相当关键:value_type, pointer, size_type
从源代码上看,这一个品种经过了一层又一层的typedef,源头难辨。
因而,大家转而从规范草案来先解读value_type

typedef typename traits::char_type      value_type;

X::char_type    ->      charT
charT           ->      char

任何四个品种也依理分析,最后得出它们的莫过于类型分别为:

www.888000ff.com 6

得结果

综上,字符串类型内存模型如下:

www.888000ff.com 7

末段让大家拿string类型来表达一下(><良心保证,下图为代码运行结果,非纯数字打印):

www.888000ff.com 8

得结果

综上,字符串类型内存模型如下:

www.888000ff.com 9

说到底让大家拿string类型来证实一下(><良心保证,下图为代码运行结果,非纯数字打印):

www.888000ff.com 10

相关文章