运营商的业绩VS重载函数调用(Performance of operator overloading

2019-09-27 16:07发布

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

<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]

Answer 1:

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

会有在性能上没有什么区别,只要有与在所有其他方面完全相同不同的名称两种功能之间在性能上没有差异。



Answer 2:

要添加到@拔示巴的答案,我做了一个快速测试一个稍微更完整的虚拟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 , 我得到完全相同装配对于两种方法 (寻找_ZNK6VectorIiEixEi = Vector<int>::operator[](int) const_ZNK6VectorIiE4ItemEi = Vector<int>::Item(int) const在组件中输出)。 这是意料之中的,因为这两个operator[]()Item()的函数调用。 操作符号只是语法糖。



Answer 3:

正如评论所说的在对方的反应,没有什么不同。

操作者将产生对操作者的呼叫,并且由于这两个函数具有相同的代码,它们所产生的相同的组件,因此,产生完全相同的性能。

为了完整起见,我试图与在接下来的输入代码铛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
}


文章来源: Performance of operator overloading vs function call