Estoy pensando en utilizar las funciones pure/const con mayor fuerza en mi código C++. (pure/const attribute in GCC)Funciones Pure/const en C++
Sin embargo, tengo curiosidad por lo estricto que debería ser y lo que posiblemente podría romperse.
El caso más obvio son salidas de depuración (en cualquier forma, podría estar en cout, en algún archivo o en alguna clase de depuración personalizada). Probablemente tenga muchas funciones, que no tienen ningún efecto secundario a pesar de este tipo de salida de depuración. No importa si la salida de depuración se realiza o no, esto no tendrá ningún efecto en el resto de mi aplicación.
O en otro caso estoy pensando en el uso de alguna clase SmartPointer que puede hacer algunas cosas adicionales en la memoria global cuando se está en modo de depuración. Si uso dicho objeto en una función pure/const, tiene algunos efectos secundarios leves (en el sentido de que algunos recuerdos probablemente serán diferentes) que no deberían tener ningún efecto secundario real (en el sentido de que el comportamiento está en de cualquier manera diferente).
Similar también para mutexes y otras cosas. Puedo pensar en muchos casos complejos donde tiene algunos efectos secundarios (en el sentido de que algunos recuerdos serán diferentes, tal vez incluso se crean algunos hilos, se hace alguna manipulación del sistema de archivos, etc.) pero no tiene diferencia computacional (todos esos efectos secundarios) bien podría ser dejado de lado y yo preferiría eso).
Por lo tanto, para resumir, quiero marcar funciones como pure/const que no son puros/const en un sentido estricto. Un ejemplo sencillo:
int foo(int) __attribute__((const));
int bar(int x) {
int sum = 0;
for(int i = 0; i < 100; ++i)
sum += foo(x);
return sum;
}
int foo_callcounter = 0;
int main() {
cout << "bar 42 = " << bar(42) << endl;
cout << "foo callcounter = " << foo_callcounter << endl;
}
int foo(int x) {
cout << "DEBUG: foo(" << x << ")" << endl;
foo_callcounter++;
return x; // or whatever
}
Tenga en cuenta que la función foo no está const en un sentido estricto. Sin embargo, no importa qué foo_callcounter está al final. Tampoco importa si la declaración de depuración no está hecha (en caso de que no se llame a la función).
que sería de esperar la salida:
DEBUG: foo(42)
bar 42 = 4200
foo callcounter = 1
Y sin optimización:
DEBUG: foo(42) (100 times)
bar 42 = 4200
foo callcounter = 100
Ambos casos son totalmente bien porque lo único que importa para mi caso de uso es el valor de retorno de la barra (42).
¿Cómo funciona en la práctica? Si marcó funciones como pure/const, ¿podría romper algo (teniendo en cuenta que el código es correcto)?
Tenga en cuenta que sé que algunos compiladores pueden no admitir este atributo en absoluto. (Por cierto, los estoy recogiendo here.) También sé cómo hacer uso de los atributos de una manera que el código se mantiene portátil (a través de #defines). Además, todos los compiladores que son interesantes para mí lo soportan de alguna manera; así que no me importa si mi código se ejecuta más lento con compiladores que no lo hacen.
También sé que el código optimizado probablemente se vea diferente según el compilador e incluso la versión del compilador.
muy relevante es también this LWN article "Implications of pure and constant functions", especialmente el capítulo "Trampas". (Gracias ArtemGr por la pista.)
¿Por qué está tan interesado en usar este atributo? ¿Ves importantes beneficios de rendimiento en código real (no artificial)? Jugué con él hace unos años y nunca vi que hiciera algo que la línea ya no estaba haciendo. – timday
Por supuesto, la línea tendría más o menos las mismas ventajas e incluso más sobre esto. Sin embargo, no solo quiere poner ** todo ** su código en los archivos de encabezado. Puede que exista una función bastante grande/grande que no desee en un encabezado, por lo que no puede estar en línea pero que todavía es pura/const. Además, puede haber casos en los que su función no sea pura/const en un sentido estricto, por lo que incluso al subrayarla no se realizarían tales optimizaciones (porque el compilador lo ve como no puro/const) pero usted tiene el conocimiento adicional de que puede ser usado como si fuera puro/const. – Albert
Consulte también el capítulo "Trucos" en http://lwn.net/Articles/285332/ – ArtemGr