通过指针访问数据成员的代价



我很想知道通过指针访问数据成员和不通过指针访问数据成员的成本是多少,所以想到了这个测试:

#include <iostream>
struct X{
    int a;
};
int main(){
    X* xheap = new X();
    std::cin >> xheap->a;
    volatile int x = xheap->a;
    X xstack;
    std::cin >> xstack.a;
    volatile int y = xstack.a;
}
生成的x86是:
int main(){
 push        rbx  
 sub         rsp,20h  
    X* xheap = new X();
 mov         ecx,4  
 call        qword ptr [__imp_operator new (013FCD3158h)]  
 mov         rbx,rax  
 test        rax,rax  
 je          main+1Fh (013FCD125Fh)  
 xor         eax,eax  
 mov         dword ptr [rbx],eax  
 jmp         main+21h (013FCD1261h)  
 xor         ebx,ebx  
    std::cin >> xheap->a;
 mov         rcx,qword ptr [__imp_std::cin (013FCD3060h)]  
 mov         rdx,rbx  
 call        qword ptr [__imp_std::basic_istream<char,std::char_traits<char> >::operator>> (013FCD3070h)]  
    volatile int x = xheap->a;
 mov         eax,dword ptr [rbx]  
    X xstack;
    std::cin >> xstack.a;
 mov         rcx,qword ptr [__imp_std::cin (013FCD3060h)]  
 mov         dword ptr [x],eax  
 lea         rdx,[xstack]  
 call        qword ptr [__imp_std::basic_istream<char,std::char_traits<char> >::operator>> (013FCD3070h)]  
    volatile int y = xstack.a;
 mov         eax,dword ptr [xstack]  
 mov         dword ptr [x],eax  

看起来非指针访问需要两条指令,而通过指针访问需要一条指令。有人能告诉我为什么这是,这将需要更少的CPU周期来检索?

我试图理解指针在访问数据成员时是否会产生更多的CPU指令/周期,而不是非指针访问。

这个测试太糟糕了。

x的完整分配如下:

mov         eax,dword ptr [rbx]  
mov         dword ptr [x],eax  

(编译器被允许对指令重新排序,并且已经这样做了)。

y赋值(编译器给了x相同的地址)是

mov         eax,dword ptr [xstack]  
mov         dword ptr [x],eax  

几乎是相同的(读寄存器指向的内存,写到堆栈)。

第一个将更复杂,除了编译器在调用new之后将xheap保存在寄存器rbx中,所以它不需要重新加载它。

在任何一种情况下,我都更担心这些访问是否错过了L1或L2缓存,而不是精确的指令。(处理器甚至不直接执行这些指令,它们在内部被转换成不同的指令集,并且可能以不同的顺序执行它们。)

通过指针访问而不是直接从堆栈访问,在最坏的情况下(获取指针)会花费额外的间接操作。这本身几乎总是无关紧要的;您需要查看整个算法,以及它如何与处理器的缓存和分支预测逻辑一起工作。

最新更新