C++ string 内存增长策略

我是研究僧i 提交于 2020-08-14 09:37:12

朝花夕拾系列缘起

时光荏苒,转眼已经毕业三年多了,而在这三年中,自己得过且过,在技术上45并无长足的长进,并且还把以往学过的知识忘记的差不多了,因此有了这个朝花夕拾的系列。寄希望于在写这些文档的同时,加深自己对C++技术的认识,并且建立梳理下自己的知识体系。


今天算是这个系列中的第一期,先剖析下C++ STL 的string类的内存增长策略,这个问题经常在面试的时候被提及,我一般都是回答,没研究过,不过应该是倍增的,也不知道面试官想要的答案是什么,自己也没深究过。没辙了,自己研究下吧。 先上一段测试代码:

 
  1.  
    // 测试字符串增长策略
  2.  
    void testStringIncrease() {
  3.  
    string strTest = "123";
  4.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  5.  
    strTest += "456";
  6.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  7.  
    strTest += "456";
  8.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  9.  
    strTest += "456";
  10.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  11.  
    strTest += "456";
  12.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  13.  
    strTest += "1234567890";
  14.  
    printf("str capacity %d, size %d\n", strTest.capacity(), strTest.size());
  15.  
    }

我们知道C++ string的设计中使用了两个属性capacity和size,分别来表示string的容量和实际占用的空间大小。string的内存都是动态增长的,因此可以猜测当size的大小要超过capacity时肯定要增加内存以容纳更多的字符。但是一次增长多少呢?又是按照怎么样的策略进行增长的呢?是否是和我上面所说的倍增增长呢?下面我们一起去揭露string内存增长的神秘面纱。

环境:VS2008 SP1

测试代码上面已经写了。下面使用VS2008的断点功能调试下。

首先我们打上断点

断点

执行进入STL源码

构造的时候先调用_Tidy方法,将成员变量_Myres = _BUF_SIZE - 1;

然后调用assign方法将传进来的字符串进行赋值

这里调用了STL的assign方法,初始构造容量肯定是0,因此需要增加3个字节的空间,调用 _Grow方法

上面已经赋值为15了而从0增长到3不用新分配内存,因此。这里全部调过。

接下来大同小异,我们直接跳到这一行代码,因为这一行代码要重新分配内存了。

同样的流程,这一直跳到 _Grow方法,出现了不同,此时【_Myres < _Newsize】条件满足,开始执行_Copy方法

然后我们苦苦追寻的亮点出现了

他的内存增长是在分配了足够的内存的基础上再和一个掩码进行|操作,这个掩码我们可以看到是15。因此这个就算是VS 2008下STL string的内存增长策略了。

而且我发现了一个亮点在VS下不同大小的字符串是存放在不同的位置的

在取字符串地址的时候我们都用的是_Myptr方法,而这个方法会根据当前字符串的容量返回两个不同的值,这两个值一个是数组存储的一个是指针,很明显可以得到结论,当字符串长度小于等于15的时候是存放在栈里的,而当字符串长度超过15到时候,又会转移到堆里面。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!