【问题标题】:How do arrays store strings in memory for C++?数组如何在 C++ 的内存中存储字符串?
【发布时间】:2021-05-08 09:03:04
【问题描述】:

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

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

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

现在,当我们使用 int、char 等原始数据类型时,这可以正常工作。

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

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

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

编辑:

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

假设向量数组会发生什么:

vector<int> v[5];

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

【问题讨论】:

  • 作为std::string 实例?!?我不明白你的问题?如果要确定字符串大小,就得用std::string::size(),sizeof(std::string)是常数。
  • @Varum 我会说字符串内存布局取决于实现,但您通常应该有 15 个字节(对于短字符串实现)加上一个指针(对于更大的字符串)。所以一个 std::string 数组将是一个固定大小、连续的字符串数组(在我的示例中,每个 15 个字节加上指针的大小,通常是 4 个字节)。

标签: c++ arrays string


【解决方案1】:

我想说字符串内存布局取决于实现,但通常应该有 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,“嘿”中的“H”的地址和 ...f070,std::string("There") 的地址之间。
  • 您会看到其他 16 个字节也被保留,可能用于指向堆的指针,以防字符串大于 16 个字节。例如。在 ...f070 和 ...f080 之间。
  • 所有 0x7ffc... 地址都应指向堆栈,0x13e8... 地址应指向堆。

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

【讨论】:

  • 当我有向量数组而不是字符串数组时会发生什么?向量是存储在数组位置还是对该向量的引用? (基本上想知道一般的对象数组)
  • @Kancha 思路类似。 std::vector 将被实现为具有给定布局的数据结构(例如,指向第一个成员的指针、大小等)。该数据结构将存储在数组位置。然后,对于每个向量,其元素将连续存储在其他地方。如果您查看另一个在线示例godbolt.org/z/b9WanYa87,您会看到向量连续存储在堆栈中,从数组地址开始,大小为 24 字节。但是,它们的元素在堆中,并且也是连续存储的。
  • 很有意义。因此,总而言之,对于对象数组,每个对象的信息将存在于数组位置,对象的元素将存储在其他地方。谢谢!
  • 没有。对象数组将每个对象存储在数组位置。碰巧std::strings 和std::vectors 是带有指向堆指针的对象,因此长字符串和向量元素存储在堆中。但并非所有对象都将信息存储在堆中:检查godbolt.org/z/1334aTs8Y,其中每个对象都是一个具有两个整数的结构,而数组最后是一个整数序列。
猜你喜欢
  • 1970-01-01
  • 2022-06-15
  • 1970-01-01
  • 2020-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多