2010-08-08 15 views
58

He leído en numerosas ocasiones que aplicar la corrección de const en el código C o C++ no solo es una buena práctica con respecto a la capacidad de mantenimiento, sino que también puede permitir que el compilador realice optimizaciones. Sin embargo, he leído todo lo contrario, también — que no afecta en absoluto el rendimiento.¿Puede la corrección de constidad mejorar el rendimiento?

Por lo tanto, ¿tiene ejemplos en los que la corrección de const puede ayudar a su compilador a mejorar el rendimiento de su programa?

+42

Const-correctness es una de las mejores prácticas en cuanto a la capacidad de mantenimiento. Si su código C++ no es const-correcto, es básicamente una pila de basura, esperando que ocurra un desastre. No tiene la intención de afectar el rendimiento. –

+1

@Neil Butterworth: desafortunadamente lo inverso no es verdad. – Beta

+3

Aquí hay un ejemplo donde 'const' hizo una diferencia de rendimiento: http://stackoverflow.com/questions/1121791/optimisation-of-division-in-gcc. Sin embargo, fue esencialmente un problema de calidad de implementación. 'const' no determinó si el compilador * podría * legalmente hacer la optimización, simplemente sucedió que la versión del compilador no pudo hacerlo cuando faltaba. –

Respuesta

50

const La corrección no puede mejorar el rendimiento porque const_cast y mutable están en el idioma y permiten que el código infrinja las reglas de forma congruente. Esto empeora en C++ 11, donde los datos de const pueden, p. Ej. ser un puntero a un std::atomic, lo que significa que el compilador debe respetar los cambios realizados por otros hilos.

Dicho esto, es trivial para el compilador mirar el código que genera y determinar si realmente escribe en una variable dada, y aplicar optimizaciones en consecuencia.

Todo lo dicho, const corrección es buena cosa con respecto a la mantenibilidad. De lo contrario, los clientes de su clase podrían romper los miembros internos de esa clase. Por ejemplo, considere el estándar std::string::c_str() - si no puede devolver un valor constante, ¡podrá atornillarlo con el búfer interno de la cuerda!

No utilice const por motivos de rendimiento. Úselo por razones de mantenimiento.

+26

"¡serías capaz de jugar con el búfer interno de la cuerda!" - Crucialmente, podrías * accidentalmente * hurgar con el buffer interno. Los errores del compilador debido a 'const' son indicadores que dicen:" estás haciendo algo estúpido ". –

+1

@Steve: Buen punto. +1 para comentar. –

+4

... y const-cast son señales que dicen: "el autor de este código está tratando de hacer algo inteligente" ;-) –

6

en mi experiencia, sin

Para las variables escalares, compilador es capaz de determinar cada vez que se cambia el valor en sí y llevar a cabo la optimización necesaria.

Para los punteros de matriz, la exactitud de const no es garantía de que los valores sean realmente constantes en presencia de posibles problemas de aliasing. Por lo tanto compilador no puede utilizar el modificador const solo para realizar optimizaciones

si usted está buscando la optimización, se debe considerar __restrict__ o funciones especiales modificadores/atributos: http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html

13

Sí, puede.

La mayoría de los const s son puramente para el beneficio del programador y no ayudan al compilador a optimizar porque es legal descartarlos y por lo tanto no le dicen al compilador nada útil para la optimización. Sin embargo, algunos const s no pueden descartarse (legalmente) y proporcionan al compilador información útil para la optimización.

Como ejemplo, el acceso a una variable global definida con un tipo const puede estar en línea, mientras que uno sin un tipo const no puede incluirse porque podría cambiar en tiempo de ejecución.

https://godbolt.org/g/UEX4NB

C++:

int foo1 = 1; 
const int foo2 = 2; 

int get_foo1() { 
    return foo1; 
} 

int get_foo2() { 
    return foo2; 
} 

asm:

foo1: 
     .long 1 
foo2: 
     .long 2 
get_foo1(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, DWORD PTR foo1[rip] ; foo1 must be accessed by address 
     pop  rbp 
     ret 
get_foo2(): 
     push rbp 
     mov  rbp, rsp 
     mov  eax, 2 ; foo2 has been replaced with an immediate 2 
     pop  rbp 
     ret 

En términos prácticos, tenga en cuenta que si bien const puede mejorar el rendimiento, en la mayoría de los casos no lo hará o lo hará, pero el cambio no será notable. La utilidad principal de const no es la optimización.


Steve Jessop da otro ejemplo en su comentario sobre la pregunta original que menciona algo que vale la pena mencionar. En un ámbito de bloque, es posible que un compilador pueda deducir si una variable se mutará y se optimizará en consecuencia, independientemente de const, porque el compilador puede ver todos los usos de la variable. Por el contrario, en el ejemplo anterior, es imposible predecir si se mutará foo1, ya que podría modificarse en otras unidades de traducción. Supongo que un hipotético compilador ultrasensible podría analizar un programa completo y determinar si es válido para acceder en línea al foo1 ... pero los compiladores reales no pueden.

Cuestiones relacionadas