与指针相比,链式公共成员访问的性能

Performance of chained public member access compared to pointer

本文关键字:成员 访问 性能 指针      更新时间:2023-10-16

由于我找不到任何有关链式成员访问的问题,但只有链式函数访问,我想问几个问题。

我有以下情况:

for(int i = 0; i < largeNumber; ++i)
{
  //do calculations with the same chained struct:
  //myStruct1.myStruct2.myStruct3.myStruct4.member1
  //myStruct1.myStruct2.myStruct3.myStruct4.member2
  //etc.
}

显然可以用一个指针来分解:

MyStruct4* myStruct4_pt = &myStruct1.myStruct2.myStruct3.myStruct4;
for(int i = 0; i < largeNumber; ++i)
{
  //do calculations with pointer:
  //(*myStruct4_pt).member1
  //(*myStruct4_pt).member2
  //etc.
}

成员访问(.)和函数访问(例如,返回指向私有变量的指针)之间有区别吗?

第一个例子将/可以由编译器优化,这是否强烈依赖于编译器?

如果在编译期间没有进行优化,CPU将/可以优化行为(例如将其保留在L1缓存中)?

链式成员访问在性能方面有什么不同吗,因为变量在编译时无论如何都是"疯狂地重新分配"的?

请不要讨论代码的可读性和可维护性,因为链式访问对我来说更清晰。

更新:

这是一个你正在修改的常量偏移量,现代编译器会意识到这一点。

但是-不要相信我,让我们问一个编译器(见这里)。

#include <stdio.h>
struct D { float _; int i; int j; };
struct C { double _; D d; };
struct B { char _; C c; };
struct A { int _; B b; };
int bar(int i);
int foo(int i);
void foo(A &a) {
  for (int i = 0; i < 10; i++) {
    a.b.c.d.i += bar(i);
    a.b.c.d.j += foo(i);
  }
}

编译成

foo(A&):
    pushq   %rbp
    movq    %rdi, %rbp
    pushq   %rbx
    xorl    %ebx, %ebx
    subq    $8, %rsp
.L3:
    movl    %ebx, %edi
    call    bar(int)
    addl    %eax, 28(%rbp)
    movl    %ebx, %edi
    addl    $1, %ebx
    call    foo(int)
    addl    %eax, 32(%rbp)
    cmpl    $10, %ebx
    jne .L3
    addq    $8, %rsp
    popq    %rbx
    popq    %rbp
    ret

如您所见,在28(%rbp)32(%rbp)两种情况下,链接已被转换为单个偏移量。