Pirateé juntos una prueba de varias funciones aquí, y esto es lo que ocurrió:
write_ushort: 7,81 s
uShortToStr: 8,16 s
convertido : 6.71 s
use_sprintf: 49.66 s
(Write_ushort es mi versión, que traté de escribir tan claro como p posible, en lugar de micro optimizar, formatear en un búfer de caracteres dado; use_sprintf es el sprintf obvio (buf, "% d", x) y nada más; los otros dos están tomados de otras respuestas aquí.)
Esta es una diferencia bastante sorprendente entre ellos, ¿no? ¿Quién pensaría usar sprintf con casi una diferencia de orden de magnitud? Oh, sí, ¿cuántas veces repetí cada función probada?
// Taken directly from my hacked up test, but should be clear.
// Compiled with gcc 4.4.3 and -O2. This test is interesting, but not authoritative.
int main() {
using namespace std;
char buf[100];
#define G2(NAME,STMT) \
{ \
clock_t begin = clock(); \
for (int count = 0; count < 3000; ++count) { \
for (unsigned x = 0; x <= USHRT_MAX; ++x) { \
NAME(x, buf, sizeof buf); \
} \
} \
clock_t end = clock(); \
STMT \
}
#define G(NAME) G2(NAME,) G2(NAME,cout << #NAME ": " << double(end - begin)/CLOCKS_PER_SEC << " s\n";)
G(write_ushort)
G(uShortToStr)
G(convert)
G(use_sprintf)
#undef G
#undef G2
return 0;
}
sprintf convirtió el toda posible rango de unsignedshorts, luego hizo toda la gama de nuevo 2.999 veces más en alrededor de 0,25 mu s por la conversión, en promedio, en mi ~ 5 años portátil.
Sprintf es portátil; ¿es también lo suficientemente eficiente para tus necesidades?
Mi versión:
// Returns number of non-null bytes written, or would be written.
// If ret is null, does not write anything; otherwise retlen is the length of
// ret, and must include space for the number plus a terminating null.
int write_ushort(unsigned short x, char *ret, int retlen) {
assert(!ret || retlen >= 1);
char s[uint_width_10<USHRT_MAX>::value]; // easy implementation agnosticism
char *n = s;
if (x == 0) {
*n++ = '0';
}
else while (x != 0) {
*n++ = '0' + x % 10;
x /= 10;
}
int const digits = n - s;
if (ret) {
// not needed by checking retlen and only writing to available space
//assert(retlen >= digits + 1);
while (--retlen && n != s) {
*ret++ = *--n;
}
*ret = '\0';
}
return digits;
}
tiempo de compilación ingrese funciones TMP no son nada nuevo, pero la inclusión de este ejemplo completo porque es lo que he utilizado:
template<unsigned N>
struct uint_width_10_nonzero {
enum { value = uint_width_10_nonzero<N/10>::value + 1 };
};
template<>
struct uint_width_10_nonzero<0> {
enum { value = 0 };
};
template<unsigned N>
struct uint_width_10 {
enum { value = uint_width_10_nonzero<N>::value };
};
template<>
struct uint_width_10<0> {
enum { value = 1 };
};
¿Ha intentado utilizar ' sprintf'/'snprintf'? Una vez hecho esto, ¿ha perfilado el código y ha determinado que se trata de un punto de acceso de rendimiento? –
Las tablas en la parte inferior del artículo vinculado a continuación ilustran claramente dónde residen las implementaciones stdlib en cuanto a la eficiencia y la optimalidad de la implementación: http://www.codeproject.com/KB/recipes/Tokenizer.aspx –