用过C++ String类的朋友们都知道它的便捷,网上也有它的实现,但个人认为,网上的实现与真正的实现是有差别的,这里简单阐述一下String类的原理。
这里借助了一个函数hexprint(),下面给出这个函数的具体实现(环境Visual Studio 2013)(见代码1):
这个函数用于输出string类的内存状况,然后我门通过下面这段代码来观察当String类存储字符串长度小于16字节和大于16字节的两种情况。(见代码2)
输出如下:
0000000f 0000000c cccccc00 21646c72 6f57206f 6c6c6548 003edb90
0000001f 0000001c cccccccc cccccccc cccccccc 003edc00 003edbc8
请按任意键继续. . .
使用sizeof()运算符可以看出,无论存储的字符串长度如何,该类所占用的内存都是28字节
第一字节:String类中的capacity()返回的字符串可能占用的内存空间
第二字节:String类中的size()返回的字符串的真实大小
当字符串长度小于16个字符时:
第三字节~第六字节:字符串本身
第七字节:一个指针,指向不详
当字符串长度大于16个字符时:
第三字节~第五字节:保留不使用
第六字节:字符串起始地址
第七字节:一个指针,指向不详
因此我门可以得出一下结论:String类存储方式较为特殊,当字符串较短时,直接存储在缓冲区中,缓冲
区大小16字节。当字符串长度超过16字节,则不使用缓冲区,开辟动态内存存储字符串。
一点个人见解,如果有补充欢迎。
//代码1:
typedef unsigned _int8 uint8;
template <typename _Type> uint8* hexprint(_Type &_Value,bool _bClean=1,const char
*_szEndlineLine="\n")
{
int _iLen = sizeof(_Type);
uint8 *_data = new uint8[_iLen];
memcpy(_data, &_Value, _iLen);
for (int _t = _iLen - 1; _t >= 0; _t--)
{
if (_data[_t] == 0)
{
printf("00");
}
else if (_data[_t] == 10)
{
printf("0a");
}
else if (_data[_t] == 11)
{
printf("0b");
}
else if (_data[_t] == 12)
{
printf("0c");
}
else if (_data[_t] == 13)
{
printf("0d");
}
else if (_data[_t] == 14)
{
printf("0e");
}
else if (_data[_t] == 15)
{
printf("0f");
}
else if (_data[_t] >= 0 && _data[_t] <= 9)
{
printf("0%d", _data[_t]);
}
else
{
printf("%x", _data[_t]);
}
if (_t % 4 == 0)
{
printf(" ");
}
}
printf(_szEndlineLine);
if (_bClean == 0)
{
return _data;
}
delete[] _data;
return NULL;
}
//代码2:
int main()
{
string StrIn16Bytes = "Hello World!";
string StrOutOf16Bytes = "I am a alien from Mars!!!!!!";
hexprint(StrIn16Bytes);
hexprint(StrOutOf16Bytes);
return 0;
}