const

De cppreference.com
Saltar a: navegación, buscar


La palabra clave const indica al compilador que el valor de una variable no cambiará después de ser inicializada. También se usa para indicar que ciertas funciones miembro de una clase no alterarán datos internos de ésta.


Contenido

[editar] Variables const

La palabra clave const en el marco de la declaración de una variable sirve el propósito de indicar que esta variable no puede ser modificada. Se puede usar de varias maneras para proteger distintas partes de una declaración de variable compuesta (por ejemplo, un puntero).

La declaración básica usando const es como sigue:

const double p = 3.1415;
...
p = sin(1.45); '' Esta línea produce un error de compilación

Una vez p ha sido declarada, su valor no puede modificarse; cualquier intento de modificar el valor de la variable directamente (vía una función o un operador de asignación) conduce a un error en la compilación.

[editar] Declaraciones Compuestas

Hasta aquí es bastante sencillo; sin embargo una vez que se empieza a trabajar con declaraciones compuestas, el uso de const se complica un poco. Un buen ejemplo es la declaración de punteros a variables, donde hay una diferencia semántica importante entre declarar el valor apuntado como constante o declarar el apuntador como constante.

const char * str; '' (1) Un puntero a caracteres que no pueden ser cambiados
char const * str; '' Una alternativa a (1)
char * const str; '' (2) Un puntero que no puede ser cambiado apuntando a caracteres

Estas declaraciones son más claras leyéndolas de derecha a izquierda como se recomienda en tipos de datos. En la expresión (1), el puntero puede ser cambiado, pero no se puede modificar los objetos (char) a los que apunta. En la expresión (2), los caracteres pueden ser cambiados, pero no se puede cambiar el valor propio del puntero.

Las referencias en C++ operan de una forma parecida, con la salvedad de considerar que una referencia no puede ser redireccionada, por tanto la referencia en sí ya es const:

const char & str; '' (3) referencia a un caracter que no puede ser modificado
char const & str; '' ídem

A esto pueden seguir declaraciones incluso más complejas como las siguientes (recordando leer de derecha a izquierda):

char * const * data; '' (4) Puntero a un puntero constante a caracteres
char const ** data; '' (5) Puntero a un puntero a caracteres constantes
const char ** data; '' (5) Ídem
char ** const data; '' (6) Puntero constante a un puntero a caracteres
char * const * const data; '' (7) Puntero constante a un puntero constante a caracteres

...Y así sucesivamente.

Una regla rápida es que si se desea que el puntero sea constante, la palabra clave const debe venir después que el puntero. Más allá de esta regla, basta con ser consistente en las declaraciones de las variables y usar el estilo y esquema de código institucional de la empresa, si es que se trabaja para alguna.


  1. ---


Es una buena práctica usar const desde etapas tempranas del desarrollo de un programa para indicar entidades que, conceptual u operacionalmente, no pueden o deben cambiar, protegiendo estos datos de modificaciones accidentales. Intentar forzar const cuando el desarrollo se encuentra ya en una fase avanzada conduce a un efecto de cascada de variables que no se pueden modificar, además de diversas frustraciones.

FIXME It is also good practice to declare certain fields of an object to be const if it is a property of the object that does not change over the life of the object.

[editar] Parámetros

El uso más común de const es el de proteger datos que son apuntados o referenciados cuando se cambia de alcance:

void func ( const MyObject * pointer ); '' MyObject no puede ser modificado por func
void func ( MyObject const * pointer ); '' Análogo a lo anterior
void func ( const MyObject & data ); '' MyObject no puede ser modificado por func
void func ( MyObject const & data ); '' Análogo a lo anterior

Dentro de las funciones aquí declaradas, las siguientes instrucciones serían inválidas:

data= function_that_returns_MyObject();
*pointer= data;


Es importante observar que colocar const antes o después de la referencia o puntero cambia la protección. Al igual que con las declaraciones de variables, const después de un puntero sólo protege el puntero, no los datos apuntados por éste:

void func ( MyObject * const pointer ); '' Pointer es constante, lo que sería innecesario (ver notas)

Dentro del cuerpo de func, será posible manipular el objeto apuntado por pointer vía la sintaxis de puntero (*pointer). Sin embargo, no será posible modificar el valor mismo del puntero (por ejemplo, para apuntarlo a otro objeto). Esto podría ser innecesario ya que al ser pasado pointer de manera local, si es cambiado las funciones que llamaron a func no pueden ver el cambio.

En comparación, colocar const después de una referencia es fútil -- las referencias ya son de por sí constantes.

void func ( MyObject & const data ); '' Protección sinsentido de data

[editar] Valor de Retorno Constante

A veces resulta útil retornar referencias constantes a un objeto (en particular cuando se trabaja con #Funciones Miembro). Cuando no queremos que la función que nos llamó sea capaz de modificar el objeto:

const MyObject & MyClass::miembro ( MyObject & data ); '' el objeto retornado por miembro no puede ser modificado

Esto debe usarse con cuidado, ya que el compilador escogerá, si se trata de asignar un valor retornado de esta función, realizar una copia a una variable. En otras palabras las dos líneas marcadas a continuación tienen distintos efectos.

MyObject ob;
MyClass a;
...
MyObject valor = a.miembro(ob);  '' (1) valor es un objeto diferente que puede ser modificado
MyObject const& referencia = a.miembro(ob); '' (2) referencia no puede ser modificado

En (1), se produce una copia del objeto no modificable a una nueva variable, la cual sí puede ser modificada; por supuesto, estos cambios no afectan a a. En (2), estamos operando directamente con el MyObject retornado desde a, por lo que no podemos modificar su valor.

[editar] Funciones Miembto

Hay circunstancias en las que una función miembro, por diseño, no cambiará variables miembro del objeto. Este tipo de miembros son llamados accessors o getters y deben declararse como const a continuación de la lista de argumentos. El efecto de esta declaración es que el puntero interno this cambia de tipo, desde un "MyClass *" a un "const MyClass *", por lo que ya no puede modificar el valor del objeto.

void MyClass::accesor ( MyOjbect & data ) const; '' esta función no cambia datos de la clase

Cuando se tiene un objeto constante (o una referencia a un objeto constante), sólo es posible llamar a aquellas funciones miembro que han sido declaradas como const. La razón de esto es que un objeto constante tiene un puntero this constante. Esta limitación es parte clave de las técnicas de encapsulación y protección de datos en el diseño de una clase.

void MyClass::const_func() const;
void MyClass::func();
 
const MyClass object;
 
object.const_func(); '' bien; miembro constante no cambiará un objeto que puede o no ser cambiado
object.func(); '' mal; miembro no-constante trataría de cambiar un objeto constante


[editar] Tópicos Relacionados

  • mutable -- declarar una variable que puede ser cambiada por miembros const
  • volatile -- declarar una variable que puede ser cambiada desde fuera del programa
  • const_cast -- remover temporalmente la propiedad constante de una variable
Herramientas personales
Espacios de nombres
Variantes
Acciones
Navegación
Herramientas
Otros idiomas