Let us suppose I create my own vector class as follows:
<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];
}
}
Let say, I have a Vector<someClass> v
. Strictly, performance-wise which of these is faster for accessing an element of the vector.
v.Item(i)
v[i]
v[i]
is merely syntactic sugar for v.operator[](i)
.
There will be no difference in performance, insofar that there is no difference in performance between two functions with different names that are identical in all other respects.
To add to @Bathsheba's answer, I did a quick test with a slightly more complete dummy Vector
implementation:
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;
}
Compiled with g++ -S
, I get exactly identical assembly for both methods (look for _ZNK6VectorIiEixEi
= Vector<int>::operator[](int) const
and _ZNK6VectorIiE4ItemEi
= Vector<int>::Item(int) const
in the assembly output). This is expected, since both operator[]()
and Item()
are function calls. The operator notation is just syntactic sugar.
As said in comments an in the other response, no difference at all.
operator will generate a call to operator, and since those two functions have the same code, they generate the same assembly, hence yielding the exact same performance.
For the sake of completeness, I tried with clang 3.7 on the following input code:
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);
}
compiled with:
clang -O3 -g -S -emit-llvm main.cpp -o main.ll
it effectively generates the exact same lines:
; 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
}