¿Qué tipo de optimización ofrece const en C/C++?

Resuelto UnTraDe asked hace 10 años • 6 respuestas

Sé que, siempre que sea posible, debes usar la palabra clave const al pasar parámetros por referencia o por puntero por razones de legibilidad. ¿Hay alguna optimización que pueda hacer el compilador si especifico que un argumento es constante?

Podría haber algunos casos:

Parámetros de función:

Referencia constante:

void foo(const SomeClass& obj)

Objeto SomeClass constante:

void foo(const SomeClass* pObj)

Y puntero constante a SomeClass:

void foo(SomeClass* const pObj)

Declaraciones de variables:

const int i = 1234

Declaraciones de funciones:

const char* foo()

¿Qué tipo de optimizaciones del compilador ofrece cada uno (si corresponde)?

UnTraDe avatar Dec 14 '14 12:12 UnTraDe
Aceptado

La siguiente es una paráfrasis de este artículo .

Caso 1:

Cuando declaras a consten tu programa,

int const x = 2;

El compilador puede optimizar esto constal no proporcionar almacenamiento para esta variable; en su lugar, se puede agregar a la tabla de símbolos. Por lo tanto, una lectura posterior solo necesita una dirección indirecta a la tabla de símbolos en lugar de instrucciones para recuperar el valor de la memoria.

Nota: Si haces algo como:

const int x = 1;
const int* y = &x;

Entonces esto obligaría al compilador a asignar espacio para x. Por tanto, ese grado de optimización no es posible para este caso.

En términos de parámetros de función, constsignifica que el parámetro no se modifica en la función. Hasta donde yo sé, no hay una mejora sustancial en el rendimiento al usar const; más bien es un medio para garantizar la corrección.


Caso 2:

"¿Declarar el parámetro y/o el valor de retorno como constante ayuda al compilador a generar un código más óptimo?"

const Y& f( const X& x )
{
    // ... do something with x and find a Y object ...
    return someY;
}

¿Qué podría hacer mejor el compilador? ¿Podría evitar una copia del parámetro o del valor de retorno?

No, ya que el argumento ya se pasa por referencia.

¿Podría poner una copia de x o algo Y en la memoria de sólo lectura?

No, ya que ambos xviven someYfuera de su ámbito y provienen y/o son dados al mundo exterior. Incluso si someYse asigna dinámicamente sobre la marcha dentro de f()sí mismo, él y su propiedad se entregan a la persona que llama.

¿Qué pasa con las posibles optimizaciones del código que aparece dentro del cuerpo de f()? Debido a la constante, ¿podría el compilador mejorar de alguna manera el código que genera para el cuerpo de f()?

Incluso cuando llama a una función miembro constante, el compilador no puede asumir que los bits del objeto xo del objeto someYno se cambiarán. Además, existen problemas adicionales (a menos que el compilador realice una optimización global): es posible que el compilador tampoco esté seguro de que ningún otro código pueda tener una referencia no constante que alias el mismo objeto como xy/o someY, y si alguna de dichas referencias no constantes. Las referencias const al mismo objeto pueden usarse incidentalmente durante la ejecución de f();y es posible que el compilador ni siquiera sepa si los objetos reales, a los cuales xy someYson meras referencias, realmente fueron declarados const en primer lugar.


Caso 3:

void f( const Z z )
{
    // ...
}

¿Habrá alguna optimización en esto?

Sí, porque el compilador sabe que zrealmente es un objeto constante, podría realizar algunas optimizaciones útiles incluso sin un análisis global. Por ejemplo, si el cuerpo de f()contiene una llamada como g( &z ), el compilador puede estar seguro de que las partes no mutables de zno cambian durante la llamada a g().

 avatar Dec 14 '2014 05:12

Parámetros de función:

constno es significativo para la memoria referenciada. Es como atar una mano a la espalda del optimizador.

Supongamos que llama a otra función (por ejemplo void bar()) en foola que no tiene una definición visible. El optimizador tendrá una restricción porque no tiene forma de saber si barha modificado o no el parámetro de función pasado foo(por ejemplo, mediante el acceso a la memoria global). La posibilidad de modificar la memoria externamente y los alias introducen restricciones significativas para los optimizadores en esta área.

Aunque no preguntó, const los valores de los parámetros de la función permiten optimizaciones porque el optimizador tiene garantizado un constobjeto. Por supuesto, el costo de copiar ese parámetro puede ser mucho mayor que los beneficios del optimizador.

Ver: http://www.gotw.ca/gotw/081.htm


Declaraciones de variables:const int i = 1234

Esto depende de dónde se declara, cuándo se crea y del tipo. Esta categoría es en gran medida donde constexisten optimizaciones. No está definido modificar un constobjeto o una constante conocida, por lo que el compilador puede realizar algunas optimizaciones; se supone que no invoca un comportamiento indefinido y eso introduce algunas garantías.

const int A(10);
foo(A);
// compiler can assume A's not been modified by foo

Obviamente, un optimizador también puede identificar variables que no cambian:

for (int i(0), n(10); i < n; ++i) { // << n is not const
 std::cout << i << ' ';
}

Declaraciones de funciones:const char* foo()

Insignificante. La memoria referenciada podrá ser modificada externamente. Si la variable referenciada devuelta por fooes visible, entonces un optimizador podría realizar una optimización, pero eso no tiene nada que ver con la presencia/ausencia de consten el tipo de retorno de la función.

Nuevamente, un constvalor u objeto es diferente:

extern const char foo[];

justin avatar Dec 14 '2014 06:12 justin