点运算符会影响效率多少?

时间:2011-11-18 10:29:58

标签: c++ performance

使用点运算符以多快的速度访问某些数据成本?例如:

struct A{
    public:
       A(): a(0){};
       int a;
};

int main(){
       A obj;
       int b = 0;

       cout << obj.a;  // How much slower is this
       cout << b;      // Than this...?

       return 0;
}

我知道我应该做基准测试,但这里有什么一般性的理解吗?

6 个答案:

答案 0 :(得分:11)

让我们来看看这些被分解的代码:

       cout << obj.a;  // How much slower is this
0041161D  mov         esi,esp 
0041161F  mov         eax,dword ptr [obj] 
00411622  push        eax  
00411623  mov         ecx,dword ptr [__imp_std::cout (41A34Ch)] 
00411629  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (41A35Ch)] 
0041162F  cmp         esi,esp 
00411631  call        @ILT+430(__RTC_CheckEsp) (4111B3h) 
       cout << b;      // Than this...?
00411636  mov         esi,esp 
00411638  mov         eax,dword ptr [b] 
0041163B  push        eax  
0041163C  mov         ecx,dword ptr [__imp_std::cout (41A34Ch)] 
00411642  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (41A35Ch)] 
00411648  cmp         esi,esp 
0041164A  call        @ILT+430(__RTC_CheckEsp) (4111B3h) 

这是在没有优化的情况下编译的。即便如此,他们也需要同样的时间。 通过优化,代码更短,但仍然大致相同:

       cout << obj.a;  // How much slower is this
00401000  mov         ecx,dword ptr [__imp_std::cout (40203Ch)] 
00401006  push        0    
00401008  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402038h)] 
       cout << b;      // Than this...?
0040100E  mov         ecx,dword ptr [__imp_std::cout (40203Ch)] 
00401014  push        0    
00401016  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (402038h)] 

因此,对于您的代码段,性能是相同的。不同的编译器可能会出现细微的差异,但开销总是可以忽略不计或为0。

答案 1 :(得分:3)

在这种情况下,可能没有,因为struct A aint b都应该优化为常量。

通常,.表示必须计算偏移量,但通常(部分)计算可以在编译时完成。这不是你应该担心的事情。此外,如果您在堆栈上有多个变量而不是单个struct,那么访问它们可能需要完全相同的偏移计算。

答案 2 :(得分:3)

基本上没有。完全没有。

这在很大程度上取决于您的情况 - 如果obj是对当前不在缓存中的内存的引用,例如,基于大型节点的结构,那么它可能会花费您。否则,它几乎为零。编译器将确保在许多甚至大多数情况下,它实际上为零。

答案 3 :(得分:2)

在您的情况下,它没有任何区别,因为obj.a可以在编译时解析,并且不会在运行时产生任何开销。您可能对this paper(pdf)感兴趣,它分析了调度虚函数调用的成本。

答案 4 :(得分:2)

使用member-access-operator时唯一的可能的运行时开销是在处理对基类的引用和调用虚函数时。但这确实只是 的可能性。通过此运算符访问成员永远不会有运行时开销。

答案 5 :(得分:1)

obj.a(&obj)->a*(int*)(&obj+0)都相同。 offset此处0已添加到起始地址。要访问它。而我在编译时并不虚拟它的计算。因此没有与之相关的额外运行时成本。