数组如何在 C++ 的内存中存储字符串?

Posted

技术标签:

【中文标题】数组如何在 C++ 的内存中存储字符串?【英文标题】:How do arrays store strings in memory for 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 个字节)。 【参考方案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::stringsstd::vectors 是带有指向堆指针的对象,因此长字符串和向量元素存储在堆中。但并非所有对象都将信息存储在堆中:检查godbolt.org/z/1334aTs8Y,其中每个对象都是一个具有两个整数的结构,而数组最后是一个整数序列。

以上是关于数组如何在 C++ 的内存中存储字符串?的主要内容,如果未能解决你的问题,请参考以下文章

如何将字符串(来自具有 n 行数的文件)存储在动态数组中? C++

c关于数组所占内存大小问题

如何在 C++ 中使用 HDF5 存储多个 2D 字符数组?

c++中数组和对象的数据是存储在栈内存还是堆内存?

c++中数组和对象的数据是存储在栈内存还是堆内存?

如何将 C++ 或 C 中的字符串转换为整数数组?