我知道如果我有一个数组int [512],引用A可以指向第一个元素.在指针算术中,内存被引用为A索引.
但是,如果我没有弄错的话,指针/引用也会占用一个机器空间.假设一个int占用一个机器字,这是否意味着上述数组的512个整数占用了513个字的空间?
对于C或C#中的对象及其数据成员,是否为true / false?
更新:哇你们快点.为了澄清,我对C和C#如何处理它们以及如何调整对象大小以适应高速缓存行(如果可能)感兴趣.
更新:我已经意识到指针和数组之间的区别.我理解数组不是指针,上面引用的指针算法只有在数组转换为指针后才有效.但我不认为这种区别与整体问题有关.我对C和C#中的数组和其他对象如何存储在内存中感兴趣.
最佳答案 请注意,当您谈论将数据拟合到缓存行时,包含引用的变量及其引用的实际数据将不会位于附近.引用将最终在寄存器中结束,但它最初可能存储为内存中其他对象的一部分,或者作为堆栈中的局部变量存储.无论与“对象”相关联的其他任何开销如何,数组内容本身在操作时仍然可以适合高速缓存行.如果您对C#中的工作原理感到好奇,Visual Studio会有一个反汇编程序视图,显示为您的代码生成的实际x86或x64程序集.
数组引用在IL(中间语言)级别具有特殊的烘焙支持,因此您将发现内存的加载/使用方式与在C中使用数组的方式基本相同.在引擎盖下,索引到一个数组是完全相同的操作.您将开始注意到的区别在于,如果使用“foreach”索引数组,或者在数组是对象类型数组时开始必须使用“unbox”引用.
请注意,当您在方法中本地实例化对象时,C和C#之间的内存位置之间的差异可能会出现. C允许您在堆栈上实例化数组,这会创建一个特殊情况,其中数组内存实际存储在“引用”和其他局部变量附近.在C#中,(托管)数组的内容总是最终在堆上分配.
另一方面,当引用堆分配的对象时,C#有时可以具有比C更好的内存,特别是对于短期对象.这是由于GC通过它们的’generation’存储对象的方式(它们活了多长时间)以及它所做的堆压缩.在不断增长的堆上快速分配短期对象;收集时,堆也会被压缩,从而防止可能导致非压缩堆中的后续分配分散在内存中的“碎片”.
您可以使用“对象池”技术(或通过避免频繁的小型短期对象)在C中获得类似的内存局部性优势,但这需要一些额外的工作和设计.当然,这样做的代价是GC必须运行,线程劫持,促进世代,压缩和重新分配引用,在某些不可预测的时间导致可测量的开销.在实践中,开销很少是一个问题,尤其是Gen0集合,它针对频繁分配的短期对象的使用模式进行了高度优化.