string 的内存大小

作者分享了写五六年C++后发现的字符串存储问题。通过代码展示,短字符串(长度不超23)中string类和字符串存于一处,最后位置存字符串长度;长字符串中,string类和字符串存于不同处,前八个字节存字符串位置,中间存长度,最后八个字节有特定含义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写了五六年的 c++ 现在才发现这个问题,也是有点丢人了😆

短一点的字符串

先搞个代码看看:

#include <bits/stdc++.h>

using namespace std;

int main()
{
    string s = "abc";
    cout << "sizeof s: " << sizeof(s) << '\n';
    cout << &s << '\n';
    char *c = &s[0];
    cout << (void *)c << '\n';
    return 0;
}

运行结果是:

sizeof s: 24
0x16ce1b400
0x16ce1b400

所以能看出来这里 string 类和字符串是存在一个地方的,那么进一步的输出:

#include <bits/stdc++.h>

using namespace std;

string s = "abc";

int main()
{
    cout << "sizeof s: " << sizeof(s) << '\n';
    cout << &s << '\n';
    char *c = &s[0];
    cout << (void *)c << "\n\n";

    char *tmp = (char *)&s;
    for (int i = 0; i <= 23; i++)
    {
        cout << dec << i << ":" << hex << (int)(*(tmp + i)) << " ";
        if ((i + 1) % 8 == 0)
            cout << '\n';
    }
    return 0;
}

输出:

sizeof s: 24
0x104bbc000
0x104bbc000

0:61 1:62 2:63 3:0 4:0 5:0 6:0 7:0 
8:0 9:0 10:0 11:0 12:0 13:0 14:0 15:0 
16:0 17:0 18:0 19:0 20:0 21:0 22:0 23:3 

前三个位置是字符串(其实还有一个’\0’),然后最后一个位置储存的是字符串的长度 3。那么问题来了,如果字符串的长度超过了 23(因为还有一个 ‘\0’ 嘛),那么又会变成啥情况捏。

长一点的字符串

修改一下代码:

#include <bits/stdc++.h>

using namespace std;

string s = string(24, 'A');

int main()
{
    cout << "sizeof s: " << sizeof(s) << '\n';
    cout << &s << '\n';
    char *c = &s[0];
    cout << (void *)c << "\n\n";

    char *tmp = (char *)&s;
    for (int i = 0; i <= 23; i++)
    {
        cout << dec << i << ":" << hex << (int)(*(tmp + i)) << " ";
        if ((i + 1) % 8 == 0)
            cout << '\n';
    }
    return 0;
}

输出:

sizeof s: 24
0x102ba8000
0x11d605f00

0:0 1:5f 2:60 3:1d 4:1 5:0 6:0 7:0 
8:18 9:0 10:0 11:0 12:0 13:0 14:0 15:0 
16:20 17:0 18:0 19:0 20:0 21:0 22:0 23:ffffff80 

这里就很明显发现有了一些变化,可以确认 string 类和字符串被储存到了不同的地方,再次修改代码之后:

#include <bits/stdc++.h>

using namespace std;

string s = string(24, 'A');

int main()
{
    cout << "sizeof s: " << sizeof(s) << '\n';
    cout << &s << '\n';
    char *c = &s[0];
    cout << (void *)c << "\n\n";

    long *tmp = (long *)&s;
    cout << hex << *(tmp) << '\n';
    cout << hex << *(tmp + 1) << '\n';
    cout << hex << *(tmp + 2) << '\n';
    return 0;
}

输出:

sizeof s: 24
0x102558000
0x130e05f00

130e05f00
18
8000000000000020

我们发现前八个字节储存的是字符串真正的位置,中间八个字节是字符串的长度,而最后八个字节(我在网上多番查找之下),我们用这里输出的8000000000000020举例,其中最高位的 “80” 固定来表示字符串被储存在了堆里面,剩下的部分则表示用于储存字符串的堆具体有多大。





作者能力有限,如果有任何错误之处,还请各位指教。(~ ̄▽ ̄)~

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值