运算符重载与函数调用的性能

时间:2016-05-19 11:53:39

标签: c++ operator-overloading

让我们假设我按如下方式创建自己的向量类:

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

3 个答案:

答案 0 :(得分:7)

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

在性能方面没有差异,因为两个不同名称的功能在所有其他方面都没有相同的性能差异。

答案 1 :(得分:1)

要添加@ 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++ -SI get exactly identical assembly for both methods进行编译(在程序集输出中查找_ZNK6VectorIiEixEi = Vector<int>::operator[](int) const_ZNK6VectorIiE4ItemEi = Vector<int>::Item(int) const)。这是预期的,因为operator[]()Item()都是函数调用。操作符号只是语法糖。

答案 2 :(得分:1)

如评论中所说,在另一个回复中,没有任何区别。

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

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

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
}

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

{{1}}