首页 > 解决方案 > 数组如何在 C++ 的内存中存储字符串?

问题描述

要访问数组中的任何随机索引,我们访问以下内存位置:

a[i] = 基地址 + (data_type 的大小) * i

这就是为什么数组只有相同类型的数据的原因。

现在,当我们使用 int、char 等原始数据类型时,这非常有效。

但是,假设我有一个字符串数组,其中每个字符串的大小不同:

string a[] = {"xyz", "abcde", "qwerty"}

这在内存中是如何工作的?由于每个字符串占用不同的内存,这在内部如何工作?

编辑 :

得到了字符串的答案。字符串在内部具有恒定的大小,因此可以解决。

在假设向量数组的情况下会发生什么:

vector<int> v[5];

它们内部是否也有恒定的大小?

标签: c++arraysstring

解决方案


我会说字符串内存布局取决于实现,但通常应该有 15 个字节(对于短字符串实现)加上一个指针(对于更大的字符串)。所以一个数组std::string将是一个固定大小、连续的字符串数组(在我的示例中,每个 15 个字节加上指针的大小,通常是 4 个字节)

你可以做这个简单的测试:打印数组中每个字符串的地址,然后打印每个字符串中第一个字符的地址。

#include <iostream>
#include <string>

int main()
{
    std::string a[] = {
        "Hey",
        "There",
        "The quick fox jumped over the brown dog",
        "Bye!"
    };
    std::cout << a << "\n";
    for (const auto& str : a)
    {
        std::cout << &str << "\n";
        const int* ptr_to_first_char = reinterpret_cast<const int*>(&(str[0]));
        std::cout << "\t" << ptr_to_first_char << "\n";
    }
}

gcc 的结果:

0x7ffc46eef050
    0x7ffc46eef060
0x7ffc46eef070
    0x7ffc46eef080
0x7ffc46eef090
    0x13e8eb0
0x7ffc46eef0b0
    0x7ffc46eef0c0
  • 您会看到实际上为每个字符串保留了 16 个字节。例如,在 ...f060,“Hey”中“H”的地址和 ...f070,地址之间std::string("There")
  • 您会看到其他 16 个字节也被保留,可能是为指向堆的指针,以防字符串大于 16 个字节。例如在 ...f070 和 ...f080 之间。
  • 所有 0x7ffc... 地址都应该指向栈, 0x13e8... 地址应该指向堆。

https://godbolt.org/z/4zK3c66Mx


推荐阅读