为什么数组中的指针不存储在连续内存中

Why are pointers in an array not stored in consecutive memory

本文关键字:连续 存储 内存 指针 数组 为什么      更新时间:2023-10-16

所以我一直在试图弄清楚这个问题,但我就是无法理解它。

如果我有这样的数组:

int numbers[] = {0,1,2,3,4,5,6,7,8,9};

每个数字将存储在连续内存中,彼此之间的距离为一个 int(在我的系统上为 4 个字节)。因此,如果我有这样的指针数组:

int* pNumbers[] = {new int(0), new int(1), new int(2)};

我希望它们存储在内存中,彼此之间有一个指针的距离(在我的系统上为 4 个字节),但事实并非如此。相反,它们以 64 字节的距离存储。此外,如果我创建一个由指向包含 int 和 bool 的结构的指针组成的数组,则距离为 72 字节。

有人可以解释一下这里发生了什么以及如何确定数组中每个元素之间的距离。

int* pNumbers[]

这将声明一个连续int *元素的数组。它们将正好相距 sizeof( int * ) 个字节。根据平台的不同,这可能介于 28 之间,但绝对不是 64 .

... = {new int(0), new int(1), new int(2)};

这会使用指向已分配内存的指针初始化元素,并使用给定值初始化内存。根据您的实现,这些指向内存的指针可以像sizeof( int )一样接近、相距很远或不连续。确切的数字未指定。

因此,数组中的int *元素将是连续的,并且正好相距sizeof( int * )。他们几乎可以指向任何地方。

这就是为什么评论员(包括我自己)怀疑你的测量有问题,即你打印指向的地址,而不是指针的地址。

你做了错误的观察。

对于int数组,您是正确的:

每个数字将存储在连续内存中,距离为 int(在我的系统上为 4 个字节)

同样,对于指针数组,每个指针将存储在连续内存中,它们之间的距离为 sizeof(int*)。这就是数组的工作方式。

我假设您查看的是指针的值,但您应该查看它们的地址

int数组的情况下,您没有查看数组元素的值(这些只是值增加 1 的整数,因为这是您存储在数组中的内容),而是查看了元素的地址。

您需要对指针数组执行相同的操作。不要查看指针的值(这些是堆上的地址,new为每个int分配了内存,因为这是您存储在数组中的内容),请查看指针的地址。

堆指针的值可能具有相当任意的值,具体取决于系统上malloc的实现详细信息。您碰巧观察到它们相距 64 个字节,但这不能保证,您不能依赖它。如果您有一个更复杂的程序来执行其他堆分配和解除分配,您可能会发现完全不同的模式,而不是每次增加固定数量的三个值。

如果你调用"new int(0)",你告诉操作系统(windows,linux,osx等)给你4个字节(sizeof(int))的数据,你可以在其中存储你的整数。操作系统可以自由地为您提供任何内存空间。

为什么你的操作系统给你的内存点相隔 64 字节,我说不出来。

结果应因运行测试的系统而异。

这是设计使然。 当您手动从堆中分配内存时,C++运行时会提供一个内存管理器(位于操作系统的内存管理器之上),并且不保证它从何处获取您分配的内存。

但是,在现代C++中,您确实希望尽可能避免分配内存。 首先,动态分配 int 非常昂贵,因为在 64 位模式下,每个 4 字节的 int 都需要 8 个字节的指针。

相反,对于 int 的动态数组,请使用 std::vector。 标准库提供了很大的灵活性,在这种简单的情况下,大部分/所有开销都将被编译掉。