繁体   English   中英

性能:C ++中的指针解引用

[英]Performance: Pointer dereferencing in C++

每当我遍历一个类中的一个数组(通过指针访问)时,我都会问自己一个同样的问题:

每次迭代是否都会通过取消引用指针而产生开销? 取消引用链加起来吗? 例如:

ClassA *a = new ClassA();
ClassB *b = new ClassB();

for( int i = 0; i < 10; i++){

   a->b->array[i].foo();

}

如果我不得不猜测,我会说这涉及20个取消引用步骤,每个指针一个,重复10次。 但是我也可以想象得到,它减少到了10个,因为编译器将链接的指针转换为单个指针。 我什至可以想象,由于某种缓存伏都教之类的东西,它减少到了1。

有人可以告诉我,也许可以向我解释这是如何表现的吗? 非常感谢!

顺便说一句,我知道这里已经回答了类似的问题,但是我无法推断出该特定主题的答案。 因此,请不要怪我再次提出这个话题。

真正要由编译器(尤其是优化器)决定如何生成代码。 在“ 假设”规则下 ,只要用户不知道程序在外部行为方式上的差异,编译器就可以执行所需的任何操作,现代编译器在应用优化方面会变得非常聪明。

在实践中,我认为最现代的优化器只有在不知道foo()内部发生了什么的情况下,才能优化循环-尤其是如果他们不能保证foo()的实现不会改变ab的值,那么它们将被强制生成代码,以便在每次循环迭代时对ab进行单独的解除引用,以确保即使ab的值发生更改也可以正确执行。

如果您不介意阅读一些汇编代码,则可以自己发现会发生什么-只需在启用优化的情况下将程序编译为汇编即可(例如g++ -O3 -S mytest.cpp )并读取生成的mytest.S文件,查看编译器做了什么。 尝试在同一文件中实现foo()(以便编译器绝对可以看到foo()的内容),并在另一个文件中实现foo(以便编译器可能不得不将foo()视为“黑色”)框”),看看有什么区别。

通过执行以下操作,可以确保摆脱一些取消引用:

// 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();

}

我希望1次内存访问,因为a和a-> b在循环内不会更改,因此无需再次获取它们。 同样,i的所有值对于a-> b-> array [i]也是已知的,因此可以预取它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM