与指针相比,链式 public 成员访问的性能
Performance of chained public member access compared to pointer
因为我找不到任何关于链式成员访问的问题,而只有链式函数访问,所以我想问几个关于它的问题。
我有以下情况:
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.
}
成员访问 (.) 和函数访问之间是否有区别,例如 returns 指向私有变量的指针?
Will/Can 第一个示例由编译器优化,这是否强烈依赖于编译器?
如果在编译期间没有进行优化,will/can CPU 优化行为(例如将其保存在 L1 缓存中)?
链式成员访问在性能方面是否完全不同,因为变量在编译期间 "wildly reassigned" 无论如何?
我恳请不要讨论关于代码的可读性和可维护性的问题,因为对于我来说,链式访问更清晰。
更新:
一切都在一个线程中 运行。
这是您正在修改的常量偏移量,现代编译器会意识到这一点。
但是 - 不要相信我,让我们问问编译器(参见 here)。
#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 , %rsp
.L3:
movl %ebx, %edi
call bar(int)
addl %eax, 28(%rbp)
movl %ebx, %edi
addl , %ebx
call foo(int)
addl %eax, 32(%rbp)
cmpl , %ebx
jne .L3
addq , %rsp
popq %rbx
popq %rbp
ret
如您所见,在以下两种情况下,链接都已转换为单个偏移量:28(%rbp)
和 32(%rbp)
。
因为我找不到任何关于链式成员访问的问题,而只有链式函数访问,所以我想问几个关于它的问题。
我有以下情况:
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.
}
成员访问 (.) 和函数访问之间是否有区别,例如 returns 指向私有变量的指针?
Will/Can 第一个示例由编译器优化,这是否强烈依赖于编译器?
如果在编译期间没有进行优化,will/can CPU 优化行为(例如将其保存在 L1 缓存中)?
链式成员访问在性能方面是否完全不同,因为变量在编译期间 "wildly reassigned" 无论如何?
我恳请不要讨论关于代码的可读性和可维护性的问题,因为对于我来说,链式访问更清晰。
更新: 一切都在一个线程中 运行。
这是您正在修改的常量偏移量,现代编译器会意识到这一点。
但是 - 不要相信我,让我们问问编译器(参见 here)。
#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 , %rsp
.L3:
movl %ebx, %edi
call bar(int)
addl %eax, 28(%rbp)
movl %ebx, %edi
addl , %ebx
call foo(int)
addl %eax, 32(%rbp)
cmpl , %ebx
jne .L3
addq , %rsp
popq %rbx
popq %rbp
ret
如您所见,在以下两种情况下,链接都已转换为单个偏移量:28(%rbp)
和 32(%rbp)
。