una tierra tension puesta prueba normas megar megado malla generador conductores como casa calculo calcular cables baja aislamiento c++ c++11 optimization reference

c++ - tension - puesta a tierra normas



En C++, ¿puedo declarar una referencia para indicar que nada la modificará? (5)

Si lo hago

typedef void Cb(); int foo(int const& a, Cb cb) { int x = a; cb(); return x - a; }

y compilar con g++ -O3 -save-temps -c foo.cpp , veo que la resta se conserva, mientras que si cb(); está comentado, toda la función se optimiza para

xorl %eax, %eax

¿Hay algo que pueda hacer a la especificación del parámetro a para que la resta se optimice independientemente de la llamada a cb() y sin forzar a que sea una referencia única (es decir, que se pueda consultar en otra parte, pero que a través de ninguna de esas referencias será modificada)?


¿Por qué no mueves el int x = a; línea debajo de la llamada de función?

Si cb() no influye ni en x ni en a , deberías hacerlo bien, y creo que el compilador optimizará la llamada nuevamente, porque x no puede cambiar entre las dos llamadas. Si hay una razón por la que no puede reordenar estas dos llamadas, probablemente no pueda optimizarlas en primer lugar.

Sin embargo, esto no es algo que pueda sugerir al compilador, ya que no hay forma de garantizar que ni x ni a hayan cambiado después de la llamada a cb() .

Piense en esto como un orden de acceso de lectura / escritura . Si no tiene acceso de lectura o escritura a a y x durante cb() , puede hacer un reordenamiento manual de la función-llamada.

Si se escribe a o x , no puede reordenar y la optimización no sería correcta.

Si se lee x , no puede reordenar la llamada a la función, pero si x realmente solo se lee, se podría leer en lugar de un, y definir x solo después de la llamada, ya que tendrá el mismo valor que a , si lo hubiera declarado antes del llamada.



Hacer la optimización sugerida sería incorrecto porque el resto del código podría ser:

static int var; void func() { var++; } // ... foo(var, func);

No tengo conocimiento de ningún atributo específico del compilador que pueda establecer para decir que cb() no modificará a .


Podría usar la restrict C en la referencia, si su compilador soporta esa extensión.
(Algunos compiladores permiten __restrict o __restrict__ , que forman parte del espacio de nombres de las implementaciones).

Esa es una promesa de usted al compilador de que el objeto no tiene alias en ninguna parte y, por lo tanto, puede optimizarlo.
Si mentiste al compilador, bueno, obtienes el código roto que mereces.


__attribute __ ((const)) es suficiente

Como se documenta en: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html , le dice al compilador que la función dada no modifica los globales (aunque puede leerlos).

También existe el subconjunto pure de const , que también prohíbe las lecturas globales.

Considere el siguiente ejemplo simplificado:

int __attribute__((const)) g(); int f(int a) { int x = a; g(); return x - a; }

En g++ 4.8 x86_64 -O3 , se compila a:

  • xor %eax,%eax con const
  • Una función grande que no supone que a no se modifique sin const

Parece que no hay un atributo de grano más fino que diga que una función no modifica una variable dada como usted lo requiere.

¿Se puede aplicar __attribute __ ((const)) a los punteros de función?

Intentemos:

int f(int& a, void __attribute__((const)) (*g)(void)) { int x = a; (*g)(); return x - a; }

Una vez más, se compila en xor %eax,%eax y en una función grande sin const , por lo que la respuesta es sí.

Esta sintaxis se solicitó en: Puntero de función a __attribute __ ((const)) function?

También apareció en 2011 en la lista de correo en: http://comments.gmane.org/gmane.comp.gcc.help/38052 Al menos al tiempo, solo funcionaba para algunos atributos.

¿Se puede agregar __attribute __ ((const)) a typedef?

Esto funciona:

typedef void __attribute__((const)) (*g_t)(void); int f(int& a, g_t g) { int x = a; (*g)(); return x - a; }

o:

typedef void (g_t)(void); int f(int& a, g_t __attribute__((const)) g) { int x = a; g(); return x - a; }

Pero no pude encontrar una manera de poner el atributo en el typedef y pasar una función, no un puntero, como:

typedef void __attribute__((const)) (g_t)(void);

GCC da una advertencia diciendo que el atributo fue ignorado en este caso.