繁体   English   中英

操作员重载与函数调用的性能

[英]Performance of operator overloading vs function call

让我们假设我创建自己的向量类,如下所示:

<template class T>
class Vector {
private:
  void** ptr;
  // More functions implementing the custom vector
public:
  T& operator[](int iIndex) const {
    return *(T*)ptr[iIndex];
  }
  T& Item(int iIndex) const {
    return *(T*)ptr[iIndex];
  }
}

假设我有一个Vector<someClass> v 严格来说,在性能方面,访问向量元素的速度更快。

  1. v.Item(i)
  2. v[i]

v[i]仅仅是v.operator[](i)语法糖。

在性能上没有任何区别,只要在其他所有方面具有相同名称的两个函数之间的性能没有区别。

为了增加@Bathsheba的答案,我使用稍微更完整的虚拟Vector实现进行了快速测试:

template <class T>
class Vector {
private:
  T* ptr;
public:
  Vector(int size)
    : ptr(new T[size])
  { }
  ~Vector()
  {
    delete[] ptr;
  }
  T& operator[](int iIndex) const {
    return ptr[iIndex];
  }
  T& Item(int iIndex) const {
    return ptr[iIndex];
  }
};

int main()
{
  Vector<int> v(5);
  v[0] = 3;
  v.Item(1) = 4;
}

g++ -S编译后, 两种方法的组装完全相同 Vector<int>::Item(int) const在组装输出中查找_ZNK6VectorIiEixEi = Vector<int>::operator[](int) const_ZNK6VectorIiE4ItemEi = Vector<int>::Item(int) const )。 这是可以预期的,因为operator[]()Item()都是函数调用。 运算符只是语法糖。

正如评论中另一个回应中所说,完全没有区别。

运算符将生成对运算符的调用,并且由于这两个函数具有相同的代码,因此它们生成相同的程序集,从而产生完全相同的性能。

为了完整起见,我尝试对以下输入代码使用lang 3.7:

 template <typename T>
class Vector {
private:
  void** ptr;


public:

    Vector(void** _ptr): ptr(_ptr) {}

  T& operator[](const int iIndex) const {
    return *(T*)ptr[iIndex];
  }

  T& Item(const int iIndex) const {
    return *(T*)ptr[iIndex];
  }
};

extern "C" int printf(const char* format, ...);

int main() {
    double a[2] = { 1.0, 2.0 };
    Vector<double> va((void**) &a);

    double a1 = va[0];
    printf("%lf\n", a1);
    double a2 = va.Item(0);
    printf("%lf\n", a2);
}

编译为:

clang -O3 -g -S -emit-llvm main.cpp -o main.ll

它有效地生成了完全相同的行:

 ; Function Attrs: nounwind uwtable  
define i32 @main() #0 {  
entry:
  %a.sroa.0.0.copyload = load double*, double** bitcast ([2 x double]* @_ZZ4mainE1a to double**), align 16, !dbg !57
  %0 = load double, double* %a.sroa.0.0.copyload, align 8, !dbg !66, !tbaa !67
  %call1 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), double %0), !dbg !72
  %1 = load double, double* %a.sroa.0.0.copyload, align 8, !dbg !76, !tbaa !67
  %call3 = tail call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0), double %1), !dbg !78
  ret i32 0, !dbg !79
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM