我们先不考虑 string 的实质是什么,先做一个实验。
执行如下代码:
int _tmain(int argc, _TCHAR* argv[])
{
string temp = "LYSM";
getchar();
return 0;
}
调试查看 temp 的地址:
修改代码为:
int _tmain(int argc, _TCHAR* argv[])
{
string temp = "LYSM|LYSM|LYSM|LYSM";
getchar();
return 0;
}
神奇,此时 temp 的内存地址中已经不会有 "LYSM|LYSM|LYSM|LYSM"
的字样了。这是因为当前的 temp 长度 > 16字节,(大于16字节的变量放在堆中存储,小于16字节的变量放在栈中存储)
😃 可以写代码验证一下:
int _tmain(int argc, _TCHAR* argv[])
{
string temp = "123456789012345"; // 长度15
int *a = (int *)malloc(sizeof(int)); // 通过 malloc 申请的内存位于堆中
int b = 0; // 通过编辑器初始化的内存位于栈中
for(auto &c:temp)
{
printf("c:%p\n", &c);
}
printf("a:%p\n", a);
printf("b:%p\n", &b);
getchar();
return 0;
}
将变量长度增加后:
int _tmain(int argc, _TCHAR* argv[])
{
string temp = "1234567890123456"; // 长度16
int *a = (int *)malloc(sizeof(int)); // 通过 malloc 申请的内存位于堆中
int b = 0; // 通过编辑器初始化的内存位于栈中
for(auto &c:temp)
{
printf("c:%p\n", &c);
}
printf("a:%p\n", a);
printf("b:%p\n", &b);
getchar();
return 0;
}
了解了这些我们大概就明白了。但是还有一点没有明了,那就是长度 > 16字节的 temp 怎么通过 &temp 去访问堆中的数据呢?
再次看一下之前的代码,下断点调试:
int _tmain(int argc, _TCHAR* argv[])
{
string temp = "LYSM|LYSM|LYSM|LYSM";
getchar();
return 0;
}
留意红框内的数值,它是一个地址:0x005d95b0,转到这个地址看一下发现我们想要的数据就在这里!
总结:
(1)string 类型小于16字节时内存位置为 变量内存地址+4。
(2)string 类型大于等于16字节时内存低地址为 [变量内存地址+4] ,也就是说原本存放在这里的数据变成了一个指针,32位进程(也就是我的)指针大小为4字节,64位进程指针大小为8字节。