[英]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
。 严格来说,在性能方面,访问向量元素的速度更快。
v.Item(i)
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.