嗯,我真的很好奇保持哪种做法更好,我知道(可能?)根本没有任何性能差异(即使在性能关键应用程序中?)但我对它的影响更加好奇生成的代码考虑了优化(为了完整性,还有“性能”,如果它有任何区别)。
所以问题如下:
元素索引的范围从A到B,其中A> 0和B> A(例如,A = 1000且B = 2000)。
要存储有关每个元素的信息,有一些可能的解决方案,其中两个使用普通数组包括直接索引访问和通过操作索引进行访问:
//declare the array with less memory, "just" 1000 elements, all elements used
std::array<T, B-A> Foo;
//but make accessing by index slower?
//accessing index N where B > N >= A
Foo[N-A];
//or declare the array with more memory, 2000 elements, 50% elements not used, not very "efficient" for memory
std::array<T, B> Foo;
//but make accessing by index faster?
//accessing index N where B > N >= A
Foo[N];
我个人会选择#2,因为我非常喜欢表演,但我认为实际上是这样:
答案 0 :(得分:2)
使用索引访问任何数组涉及添加索引乘以元素大小并将其添加到数组本身的基址。
由于我们已经在另一个号码中添加了一个号码,因此在添加foo[N-A]
之前,可以通过N * sizeof(T)
向下调整基址来轻松完成A * sizeof(T)
的调整,而非实际计算(A-N)*sizeof(T)
。
换句话说,任何体面的编译器都应该完全隐藏这个减法,假设它是一个常量值。
如果它不是常数[假设您使用std::vector
std::array
{/ 1}},那么您确实会在某个时刻从A
减去N
代码。这样做还是相当便宜的。大多数现代处理器可以在一个周期内完成此任务,结果没有延迟,因此在最坏情况下会为访问添加一个时钟周期。
当然,如果数字是1000-2000,那么在整个方案中可能几乎没有什么区别 - 要么处理的总时间几乎没有,要么是因为你做了复杂的事情。但是如果你要将它变成一百万个元素,相互抵消50万个元素,那么它可能会在分配它们的简单或复杂方法之间产生差异,或者说是一些这样的元素。
此外,正如Hans Passant所暗示的那样:现代操作系统具有虚拟内存处理功能,实际使用的内存并没有填充真正的内存&#34;。在工作中,我正在调查具有2GB RAM的电路板上的一个奇怪的崩溃,并且在查看内存使用情况时,它显示这一个应用程序已经分配了3GB的虚拟内存。该板没有交换盘(它是嵌入式系统)。事实证明,有些代码只是简单地分配了大量没有任何东西的内存,只有当它达到3GB(32位处理器,3 + 1GB内存分配在用户/内核空间之间)时它才停止工作。因此,即使对于大块内存,如果你只有一半的内存,如果你实际上没有访问它,它实际上不会占用任何RAM。
总而言之,就性能,编译器等而言,如果它很重要,就不要相信互联网&#34;告诉你答案。使用您计划使用/ for生成代码的实际编译器和处理器类型,使用您实际打算使用的代码设置测试,并运行基准测试。某些编译器可能会出现错误(在处理器类型XYZ9278上),这会导致它为大多数其他编译器执行此操作的情况生成可怕的代码,而且根本没有开销#34;