gpt4 book ai didi

c++ - 多个指针取消引用与引用之间的性能差异

转载 作者:可可西里 更新时间:2023-11-01 17:14:13 26 4
gpt4 key购买 nike

这是几个月前我问的一个面试问题:

以下哪个函数执行得更快,Foo1 还是 Foo2

void Foo(SomeObjectArray** array, unsigned int size)
{
for (int i = 0; i < size; i++)
{
if (((*array) + i) != NULL)
{
((*array) + i)->Operation1();
((*array) + i)->Operation2();
((*array) + i)->Operation3();
((*array) + i)->Operation4();
((*array) + i)->Operation5();
((*array) + i)->Operation6();
}
}

void Foo(SomeObjectArray** array, unsigned int size)
{
for (int i = 0; i < size; i++)
{
if (*((*array) + i) != NULL)
{
Object& obj = *((*array) + i);
obj.Operation1();
obj.Operation2();
obj.Operation3();
obj.Operation4();
obj.Operation5();
obj.Operation6();
}
}
}

请注意,这是靠内存,所以我记不清具体的代码了,但大体思路是一样的。一个函数使用指针,而另一个使用引用(它可能有一个指向数组的指针,就像上面的代码一样,但我记不太清了)。我说 我不确定,并且必须分析代码才能找出答案,但如果我不得不猜测 Foo2“可能”更快。他们没有留下深刻印象...

当我遇到与此类似的代码(或编写它)时,这让我在这里和那里唠叨了几次,并且想知道在这种情况下我应该做什么。

我知道...

  1. 这是一个微优化
  2. 编译器很可能会优化它

EDIT: I have changed the code slightly so that now it is checking for a NULL pointer.

最佳答案

我认为这是一个非常有趣的问题,我看到了很多关于编译器可能做什么的猜测,但我想仔细看看并确定一下。所以我采用了 e.James 的程序并通过 GCC 运行它以获取程序集。我应该说我不太了解汇编,所以如果我错了,请有人纠正我,但我认为我们可以合理地推断出发生了什么。 :)

使用-O0 编译(无优化)

对于Foo1,我们看到数组偏移量是在每次函数调用之前计算的:

movl    8(%ebp), %eax
movl (%eax), %edx
movl -4(%ebp), %eax
leal (%edx,%eax), %eax
movl %eax, (%esp)
call __ZN10SomeObject10Operation1Ev

这是所有六个方法调用,只是使用了不同的方法名称。 Foo2 有一些设置代码来获取引用

movl    8(%ebp), %eax
movl (%eax), %edx
movl -4(%ebp), %eax
leal (%edx,%eax), %eax
movl %eax, -8(%ebp)

然后其中六个,看起来只是堆栈指针推送和函数调用:

movl    -8(%ebp), %eax
movl %eax, (%esp)
call __ZN10SomeObject10Operation1Ev

在没有优化的情况下,几乎是我们所期望的。输出是

Foo1: 18472
Foo2: 17684

使用 -O1 编译(最小优化)

Foo1 效率稍微高一点,但每次还是把数组偏移量加起来:

movl    %esi, %eax
addl (%ebx), %eax
movl %eax, (%esp)
call __ZN10SomeObject10Operation1Ev

Foo2 看起来保存了 ebx 的值(addl (%edi), %ebx),然后进行这些调用:

movl    %ebx, (%esp)
call __ZN10SomeObject10Operation1Ev

这里的时间是

Foo1: 4979
Foo2: 4977

使用-O2编译(适度优化)

当使用 -O2 编译时,GCC 只是摆脱了整个事情,每次调用 Foo1Foo2 只会导致添加 594到 dummy(99 次增量 * 6 次调用 = 594 次增量):

imull   $594, %eax, %eax
addl %eax, _dummy

没有调用对象的方法,尽管这些方法保留在代码中。正如我们所料,这里的时代是

Foo1: 1
Foo2: 0

我认为这告诉我们 Foo2 在没有优化的情况下会快一点,但实际上这是一个有争议的问题,因为一旦它开始优化,编译器只是在堆栈和寄存器。

关于c++ - 多个指针取消引用与引用之间的性能差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5822031/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com