杰表技术论坛 's Archiver

admin 发表于 2018-6-30 13:07

std::string 和 vector<char> 两者的内存布局是怎么样的,有什么区别?

待考

admin 发表于 2018-6-30 17:39

c++ stl ,如何实现,没有规定,各家有各家的配方,vc2013 stl 中的 string 数据成员简写形式:
class string
{
        allocate_proxy * proxy; // 内存申请管理器  4字节
        union _Bxty //16个字节
                {        
                char _Buf[16]; // 短字符串保存在这里,
                char * _Ptr;    //  当使用动态申请内存时new char[n],这个成员指向申请到的内存
                char _Alias[16];        // 什么鬼?
                } _Bx;

        size_type _Mysize;        // 字符串长度,不包含'\0' 4字节
        size_type _Myres;        // 保留的字节数 4字节
}        

现在的stl实现,多数都采用 SOO(small object optimization) 技术,即小对象优化技术,对字符串来说,也可称 SSO(small string optimization), 做法是将短串保存在类内存里,超过一定长度的字符串数据,才通过动态申请内存来保存。之所以这样做,是考虑到申请动态内存,开销大,减少动态申请,可以提高程序效率,是典型的以空间换效率的做法,关于SSO, 可参照文章:[url=https://shaharmike.com/cpp/std-string/]https://shaharmike.com/cpp/std-string/[/url]

vc2013的string实现,就是基于这样的思想。在 vc2013 中,sizeof std::string 为 28 个字节,从上述得知 , 4+16+4+4 = 28个字节, 注意_Bx._Buf预留了16个字节的,用来保存长度不超过15的短串,这样的短串,直接复制这里,类似:
string x("hello");
等价:
string x;
strcpy(x._Bx._Buf,"hello");
x._Mysize = strlen("hello");
x._Myres = 15;

如果大于15的串,如:
string x("i am big string abcdefghijklm.....................");
等价于:
string x;
x._Bx._Ptr = new char[strlen("i am big string abcdefghijklm.....................")+1]; // 实际可能会多申请一些内存,这里简化了,用多少申请多少
x._Mysize = strlen("i am big string abcdefghijklm.....................");
x._Myres = x._Mysize; // 当申请得多,保留数与字符串长度会不一样

那怎么知道,实际保存的字符串地址在哪里,以下的 string::c_str() 实现可回答这个问题:

const * char string::c_str()
{
     if(this._Myres >15) // 是长串,
         {
             return _Bx._Ptr; // 返回动态申请的地址
         }else
         {
                return _Bx._Buf ; // 是短串,返回本地地址
         }
}
可以看出,当长串时,union的16个字节,只用了开始的四个字节有效,来表示动态内存地址,其余12个字节没用,典型的用空间换效率的做法。

页: [1]

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.