每次我循环一个类中的数组,我通过指针访问,我问自己同样的问题:
每次迭代是否通过解除引用指针产生开销?解除引用链加起来了吗? 例如:
ClassA *a = new ClassA();
ClassB *b = new ClassB();
for( int i = 0; i < 10; i++){
a->b->array[i].foo();
}
如果我不得不猜测,我会说这涉及20个解除引用步骤,每个指针一个,10次迭代。 但我可以想象一下,它被减少到10,因为编译器将链式指针转换为单个指针。我甚至可以想象,它被减少到1,因为一些缓存 - 伏都教或其他东西。
有人可以告诉我,也许可以向我解释一下,这表现如何表现?非常感谢!
是的,我知道这里已经回答了类似的问题,但是我无法推断出这个特定主题的答案。所以请不要责怪我再次提出这个话题。答案 0 :(得分:3)
它真的取决于编译器(特别是优化器)如何生成代码。在as-if rule下,只要用户无法区分程序在外部的行为方式,编译器就可以做任何想做的事情,而现代编译器可以非常聪明地应用它们。< / p>
在实践中,我认为最现代的优化器只有在他们无法分辨foo()内部发生的情况时才能优化循环 - 特别是,如果他们不能保证foo( )&#39}的实施不会更改a
或b
的值,然后他们将被迫生成代码,对a
和b
进行单独的解除引用对于每个循环迭代,只是为了确保即使a
或b
的值发生变化也会发生正确的事情。
如果您不介意阅读一些汇编代码,您可以自己了解会发生什么 - 只需将程序编译为汇编,启用优化(例如g++ -O3 -S mytest.cpp
)并阅读生成的mytest .S文件看看编译器做了什么。尝试使用在同一文件中实现的foo()(以便编译器可以确定地看到foo()的内容)并使用foo在不同的文件中实现(这样编译器可能必须将foo()视为一个黑盒子&#39;),看看它有什么不同。
答案 1 :(得分:3)
你可以通过这样做来确保摆脱一些解除引用:
// create a pointer to the b class outside of the loop
ClassB * bptr = a->b;
// use the pointer inside the loop
for( int i = 0; i < 10; i++){
bptr->array[i].foo();
}
答案 2 :(得分:1)
我希望有1个内存访问,因为a和a-&gt; b在循环内不会改变,所以不需要再次获取它们。 i的所有值都是a-&gt; b-&gt; array [i],因此可以预取。