2011-08-03 15 views
7

Si tengo una función que solo existe por un corto período de tiempo, ¿hacer la lista de colores una constante hace la diferencia?¿Hay algún beneficio al declarar una const en lugar de una variable dentro de una función?

string getrandcolor(){ 
    const string colors[5] = {"red", "blue", "green", "yellow", "purple"}; 
    return colors[rand() % 5]; 
} 

Nota: La lista real de colores contiene cientos de colores no sólo la pequeña muestra que he mostrado, no estoy seguro si esto hace la diferencia tampoco.

+0

¿Llama a esta función con frecuencia? – Cameron

+2

@Tommy: la cadena se copia a la devolución, ya que se devuelve por valor. – Cameron

+0

@ Cameron: Whoops, por alguna razón, pensé que estaba devolviendo un puntero. –

Respuesta

16

Le impide sobrescribir accidentalmente las variables que no quiso cambiar. "¡Uy!" - la protección es probablemente la función más importante de const.

Hipotéticamente un compilador podría adivinar algún tipo de optimización al saber que una variable no debería cambiar, pero mis pruebas nunca han encontrado una que realmente haga algo significativo en la situación que describes.

const staticdoes tienen una diferencia importante en su muestra de código particular. Como su matriz de colores [] es local, debe construirse de nuevo cada vez que se llame a la función getrandcolor(). Eso significa que el constructor de cadenas se ejecuta cinco veces cada vez que llamas al getrandcolor(), lo cual es muy inútil. const static significa que los datos se construyen una sola vez — la primera vez que se ejecuta la función — y se colocan en un espacio de memoria compartida.

+4

'static' es probable que tenga más impacto que' const' aquí así que +1 por mencionarlo. – paxdiablo

+2

"Debe construirse de nuevo" No estoy seguro de que esto sea cierto. Probablemente _will_ be, pero no creo que "debe ser" es exacto. –

+0

Eso es realmente interesante gracias, sin embargo, ¿qué pasaría si tuviera la función A con la variable X y la función B con otra variable llamada X y ambas fueran del mismo tipo pero se suponía que fueran diferentes, heredarían los datos de cada uno ? –

2

Si está hablando de rendimiento, entonces: no, no debería hacer ninguna diferencia.

2

Al declarar una variable local una constante, se obtienen los siguientes beneficios:

  • Corrección: el compilador se asegurará de que no va a cambiar accidentalmente el valor de la variable.
  • Claridad: documentan claramente que la variable es una constante.

(Por cierto, no estoy seguro de lo que es constante en ese ejemplo específico. Más pronto ...)

+1

Las cadenas son constantes. 'colors' es una' matriz lvalue de 5 cadenas constantes'. –

+0

Acabo de comprobarlo :) –

+1

¿Qué más sería constante? –

5

En términos de rendimiento? No, probablemente no. Parece que su matriz también podría ser static, y luego quizás .

En términos de estilo de código? Posiblemente. Aunque la adición de const hace que su código sea un poco detallado, también deja en claro que los datos no se deben modificar. Esto es que documenta y seguro.


Lo ideal sería que todos los objetos en C++ sería constantes por defecto, y que tendría que escribir mutable para que sean variables. ¡Todo es al revés!

+5

"Idealmente, todas las ** variables ** en C++ serían ** const ** por defecto" - pensemos en eso un poco :-) – paxdiablo

+0

@paxdiablo: Objects. "Idealmente, todas las variables en C++ serían _instead_ const por defecto". Cállate. :) –

+0

Idealmente, las "variables" se denominarían "objetos con nombre" ;-) –

2

Hablando de interpretaciones, pero también de legibilidad de código, debe crear la variable "colores" fuera de la función (ya que una matriz de cien tamaños es una gran cantidad de código, enmascarando la lógica de la función) en una inicialización función, o a nivel mundial. Si no considera extraer esta variable, al menos, hágalo estático.

Si este conjunto se utiliza solo durante un período corto durante la ejecución del programa, puede considerar completarlo antes de la primera llamada a getcolors y finalmente liberarlo cuando esté seguro de que ya no lo necesitará.

1

ejemplo ligeramente diferente:

const int *global_ptr = 0; 

void bar(); 

void foo() { 
    int x = 1; 
    global_ptr = &x; 
    bar(); 
    std::cout << x << "\n"; 
} 

El compilador no puede optimizar la última línea para utilizar el valor 1, porque para todo lo que sabe, bar() toma el valor de global_ptr, lo convierte en int*, y modifica x a través eso. Esta sería una codificación algo arriesgada, pero descartar un calificador const y mutar es válido siempre que la referencia sea realmente mutable, por lo que el compilador debe permitirlo.

Pero, si x fueron marcados const entonces sería válido bar() para desechar const y mutar, por lo que el optimizador es libre de asumir que x todavía mantiene el valor 1 cuando se imprime.

Los optimizadores sin duda identifican las constantes de tiempo de compilación para este tipo de optimización, por lo que no me sorprendería ver que hace una diferencia para el código emitido. Cuánta diferencia hace en el rendimiento, no lo sé. No es difícil generar casos donde identificar una constante puede, por ejemplo, reemplazar una división (costosa) con algunos giros de bits más baratos, o puede permitir que expresiones que involucren x y un montón de otras constantes se calculen en tiempo de compilación en lugar de tiempo de ejecución.

Además, la optimización en tiempo de enlace podría permitir bar a ser inline, en cuyo caso el optimizador de tiempo de enlace puede inspeccionar su contenido más de cerca, y podría ser capaz de descartar su modificación x incluso en el caso no constante.

En su ejemplo, sin embargo, ninguna referencia a colors puede escapar a un código desconocido, por lo que la diferencia no aparece. De todos modos, una cadena const es probablemente más difícil de optimizar que const int, por lo que hay menos posibilidades de que estés habilitando alguna optimización brillante usando const.

Cuestiones relacionadas