数组内存分配和使用 - 四的倍数

时间:2013-08-17 01:23:07

标签: c++ arrays

这是来自记忆,所以我可能会误用几句话,但意思应该是可以理解的

我目前在大学,主修编程 - 我们开始使用C ++,当我们开始使用数组时,我们的C ++老师(一位有着奇怪想法和编程规则的老师,比如没有任何评论允许)告诉我们我们应该使我们的数组大小为4的倍数更有效:

char exampleArrayChar[ 4 ]; //Allowed
float exampleArrayChar[ 6 ]; //NOT Allowed
int exampleArrayChar[ 8 ]; //Allowed

他说这背后的原因是因为计算机进行内存分配的方式。

计算机以4个字节为一组分配每个数组元素的内存地址/位置 - 因此在2个内存组中完成了8个元素的数组。

所以问题是,如果你创建了一个大小为6的数组,它会分配2组4,但是然后将这些字节中的2个(在8个中)标记为无效/无效,使它们无法使用直到整个数组从记忆中释放出来。

虽然这对我来说听起来似乎有点其他计算机数学(例如1gb = 1024mb而不是1000)我有兴趣知道:

  • 这是多么真实,以及通过这样做获得的收益(如果有的话)
  • 这只是C ++吗? (我会假设没有,但仍然值得一提)
  • 关于这一切的更多信息 - 例如,为什么4?计算机数学通常不是二进制的,因此2是?

在网上浏览我一直无法找到任何主要用途或相关性。

4 个答案:

答案 0 :(得分:8)

float exampleArrayChar[ 6 ]; //NOT Allowed

考虑到float是4个字节(几乎普遍,由于广泛采用IEEE-754编码的浮点数),任何数量的浮点数已经是4个字节的倍数。你的例子是24,并没有问题。在x86(和x64)上,SSE指令确实更喜欢数据为8字节对齐...再次使用大小为6个元素的float数组= 24字节不会干扰这一点。

对齐真正重要的唯一更大的倍数是缓存行的大小,它随实现而变化很大(为x86编译的代码可能会发现自己在具有32字节,128字节或其他缓存大小的CPU上运行,全部来自相同的机器代码)。并且高速缓存对齐可以产生很大的性能差异,但是与高速缓存行的对齐不一定更好,事实上它通常很多更糟要对齐,因为它会引起缓存映射上的冲突,类似于false就性能影响而言,就共享而言。

请参阅What is "cache-friendly" code?Why is my program slow when looping over exactly 8192 elements?以及其他相关问题。

但是一旦你的教授没有任何评论允许你应该在院长办公室要求退还你的学费。

答案 1 :(得分:3)

假设你的老师真的告诉你你上面说的是什么,你的老师就错了(这根本不会让我感到惊讶)。然而,真实的是,当你从堆中分配内存时,分配的内存块可能是2的幂的倍数,因为内存最终会以不幸的方式被分割,否则,至少在使用通用时内存分配器。因此,您可能会浪费几个字节。但是,除非你有很多对象,否则我不会理会这些细节:首先使用语义正确的方法使程序正确。

然而,处理这些问题的最佳方法不是首先使用数组,而是使用std::vector<T>std::deque<T>

答案 2 :(得分:1)

那位老师有一些非常时髦(和错误的想法)。为了解释为什么要检查每个陈述。

  

...我们的C ++老师......告诉我们我们应该制作数组大小   4的倍数更有效......他说这背后的原因   是因为计算机分配内存空间的方式(空格   可能不是正确的工作 - 基本上每个的内存地址   数组中的元素)

C(和C ++)授予如果分配内存,无论类型如何,它都会存在,否则会发生运行时错误。他可能会说的是,分配更多空间(例如,容纳一些溢出错误)是一种很好的做法(不是)。 但是C和C ++授予静态的所有内存(我的意思是不通过new()动态声明,虽然我不确定这个)数组是连续的。 在声明某些内容时,只使用您需要使用的内存量(资源)。

  

计算机为每个阵列分配了内存地址/位置   四个一组的元素 - 所以在2个内存中完成了8个元素的数组   组(再次,组不是正确的词)

int至少是4个字节,这是听到之前引用有意义的唯一句子。由于您可以通过引用引用内存中的任何字节,因此除非出现一些环境问题,否则不需要以四个为一组分割内存。

  

虽然这对我来说在其他计算机数学方面听起来似乎有道理   (例如1gb = 1024mb而不是1000)......

虽然在其他地方最好讨论,但GB和GiB是分开的东西;在维基百科上查看。然而,当关于记忆时,有一个非正式的惯例,即字节单元的'倍数在2 10 上排序,2 20 ,2 30 等等。

最后,正如之前的评论者所说,C ++中的正确的做事方式是通过新的容器类,std::vector<T>是最像数组的容器。将这种数组声明保留为非常简单或遗留的C代码。

答案 3 :(得分:1)

最近,当我在探究超级用户时,我遇到了一篇描述碎片的帖子,这导致我在维基百科上发帖this。引用:

  

例如,内存只能以块的形式提供给程序   可以被4,8或16整除,因此如果程序可能请求   23个字节,它实际上会得到24个块。当这种情况发生时,   多余的记忆浪费了。在这种情况下,无法使用的内存是   包含在分配的区域内,因此被称为内部   碎片。

尽管如此,正如大多数人所指出的那样,“节省”的空间量并不是什么大不了的事,因为在大多数现代系统中存在大量内存(GB);最好根据程序的需要进行设计,而不是根据机器的需要进行设计。