Como otros han sugerido hablar con su colega y pedirle que explique su razonamiento. Si es práctico, debe investigar con un pequeño programa de prueba el rendimiento de las dos versiones. Hacer ambas cosas te ayudará a crecer como programador.
En general, estoy de acuerdo con los consejos para hacer que la función miembro sea estática si es práctica. No por razones de rendimiento, sino porque reduce la cantidad de contexto que necesita recordar para comprender el comportamiento de la función.
Vale la pena señalar que hay un caso en el que el uso de una función miembro dará como resultado un código más rápido. Ese caso es cuando el compilador puede realizar la alineación.Este es un tipo de tema avanzado pero es algo así que dificulta escribir reglas categóricas sobre programación.
#include <algorithm>
#include <iostream>
#include <vector>
#include <stdlib.h>
#include <time.h>
bool int_lt(int a, int b)
{
return a < b;
}
int
main()
{
size_t const N = 50000000;
std::vector<int> c1;
c1.reserve(N);
for (size_t i = 0; i < N; ++i) {
int r = rand();
c1.push_back(r);
}
std::vector<int> c2 = c1;
std::vector<int> c3 = c1;
clock_t t1 = clock();
std::sort(c2.begin(), c2.end(), std::less<int>());
clock_t t2 = clock();
std::sort(c3.begin(), c3.end(), int_lt);
clock_t t3 = clock();
std::cerr << (t2 - t1)/double(CLOCKS_PER_SEC) << '\n';
std::cerr << (t3 - t2)/double(CLOCKS_PER_SEC) << '\n';
return 0;
}
En mi i7 Linux porque g ++ no puede inline la función int_lt pero puede inline std :: :: menos operador() la versión no es miembro de la función alrededor del 50% más lento.
> g++-4.5 -O2 p3.cc
> ./a.out
3.85
5.88
Para entender por qué una diferencia tan grande, debe tener en cuenta qué tipo de infiere el compilador para el comparador. En el caso int_lt infiere el tipo bool (*) (int, int) mientras que con std :: less infiere std :: less. Con el puntero de función, la función a la que se llama solo se conoce en tiempo de ejecución. Lo que significa que es imposible para el compilador alinear su definición en tiempo de compilación. A diferencia de std :: less, el compilador tiene acceso al tipo y su definición en tiempo de compilación, de modo que puede alinear std :: less :: operator(). Lo que hace una diferencia significativa en el rendimiento en este caso.
¿Este comportamiento solo está relacionado con las plantillas? No, se relaciona con una pérdida de abstracción al pasar funciones como objetos. Un puntero de función no incluye tanta información como un tipo de objeto de función para que el compilador use. Aquí hay un ejemplo similar que no usa plantillas (aparte de std :: vector para mayor comodidad).
#include <iostream>
#include <time.h>
#include <vector>
#include <stdlib.h>
typedef long (*fp_t)(long, long);
inline long add(long a, long b)
{
return a + b;
}
struct add_fn {
long operator()(long a, long b) const
{
return a + b;
}
};
long f(std::vector<long> const& x, fp_t const add, long init)
{
for (size_t i = 0, sz = x.size(); i < sz; ++i)
init = add(init, x[i]);
return init;
}
long g(std::vector<long> const& x, add_fn const add, long init)
{
for (size_t i = 0, sz = x.size(); i < sz; ++i)
init = add(init, x[i]);
return init;
}
int
main()
{
size_t const N = 5000000;
size_t const M = 100;
std::vector<long> c1;
c1.reserve(N);
for (size_t i = 0; i < N; ++i) {
long r = rand();
c1.push_back(r);
}
std::vector<long> c2 = c1;
std::vector<long> c3 = c1;
clock_t t1 = clock();
for (size_t i = 0; i < M; ++i)
long s2 = f(c2, add, 0);
clock_t t2 = clock();
for (size_t i = 0; i < M; ++i)
long s3 = g(c3, add_fn(), 0);
clock_t t3 = clock();
std::cerr << (t2 - t1)/double(CLOCKS_PER_SEC) << '\n';
std::cerr << (t3 - t2)/double(CLOCKS_PER_SEC) << '\n';
return 0;
}
Las pruebas de comprobación indican que la función gratuita es 100% más lenta que la función miembro.
> g++ -O2 p5.cc
> ./a.out
0.87
0.32
Bjarne Stroustrup brindó una excelente conferencia recientemente sobre C++ 11 que trata sobre esto. Puedes verlo en el siguiente enlace.
http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Keynote-Bjarne-Stroustrup-Cpp11-Style
suena muy dudosa para mí, y, a menos que se está ejecutando en algún punto de acceso rendimiento, completamente irrelevante. – spencercw
Nunca te ves estúpido por hacer preguntas. Si él piensa que eres entonces ÉL ES ESTÚPIDO. Preguntar es cómo nos hacemos mejor. – Iznogood
@spencercw: ¿Pero por qué hacer que una función sea una función miembro si puede ser estática? Incluso desde una perspectiva de diseño que no tiene sentido. –