Espacios de nombres
Variantes
Acciones

cv (calificadores de tipo const y volatile)

De cppreference.com
< cpp‎ | language
 
 
 
 

Aparecen en cualquier especificador de tipo, incluyendo la sec-decl-especificadores de la gramática de declaraciones, para especificar la constantitud o la volatilidad de un objeto que está siendo declarado o del tipo que se le está dando nombre.

  • const - Define que el tipo es constante.
  • volatile - Define que el tipo es volátil.

Contenido

[editar] Explicación

Para cualquier tipo T (incluyendo tipos incompletos), además de tipos función o tipos referencia, existen tres tipos distintos adicionales en el sistema de tipos de C++: calificado-const T, calificado-volátil T, y calificado-const-volátil T.

Nota: Los tipos array se consideran que tienen la misma calificación-cv que los tipos de sus elementos.

Cuando un objeto se crea por primera vez, los calificadores-cv utilizados (que podrían ser parte de una sec-decl-especificadores o parte de un declarador en una declaración, o parte de un id-de-tipo en una expresión-new) determinan la constantitud o la volatilidad de un objeto de la siguiente manera:

  • objeto const - Un objeto cuyo tipo es calificado-const, o un subobjeto no-mutable de un objeto const. Tal objeto no puede ser modificado: intentar hacerlo directamente es un error en tiempo de compilación, e intentar hacerlo indirectamente (p. ej., modificando un objeto const mediante una referencia o un puntero a un tipo no const) resulta en comportamiento indefinido.
  • objeto volátil - Un objeto cuyo tipo está calificado-volátil, o un subobjeto de un objeto volátil, o un subobjeto mutable de un objeto const-volátil. Cada accesso (operación de lectura o de escritura, llamada a función miembro, etc.) hecho a través de una expresión glvalue de un tipo calificado-volátil se trata como un efecto secundario visible para los propósitos de optimización (es decir, dentro de un solo hilo de ejecución, los accesos volátiles no pueden ser optimizados o reordenados con otro efecto secundario visible que es secuenciado-antes o secuenciado-después del acceso volátil. Esto hace a los objetos volátiles adecuados para la comunicación con un controlador de señales, pero no con otro hilo de ejecución. Véase std::memory_order). Cualquier intento de referirse a un objeto volátil a través de un glvalue no volátil (p. ej., mediante una referencia o un puntero a un tipo no volátil) resulta en comportamiento indefinido.
  • objeto const volátil - Un objeto cuyo tipo está calificado-const-volátil, un subobjeto no mutable de un objeto const volátil, un subobjeto const de un objeto volátil, o un subobjeto no mutable de un objeto const. Se comporta tanto como un objeto const como un objeto volátil.

[editar] Especificador mutable

  • mutable - Permite la modificación de un dato miembro declarado como mutable aún si el objeto que lo contiene se declara como const.

Puede aparecer en la declaración de un dato miembro no estático de tipo referencia no const:

class X {
  mutable const int* p;         // de acuerdo
  mutable int* const q;         // mal formado
};

El especificador mutable se utiliza para especificar que un dato miembro no afecta el estado externamente visible de la clase (y frecuentemente se usa para mutexes, cachés de memoria, evaluación perezosa e instrumentación de acceso).

class ContadorSeguroParaHilos {
  mutable std::mutex m; // La "regla M&M": mutable y mutex van juntos
  int datos = 0;
 public:
  int get() const {
    std::lock_guard<std::mutex> lk(m);
    return datos;
  }
  void inc() {
    std::lock_guard<std::mutex> lk(m);
    ++ datos;
  }
};

[editar] Conversiones

Existe un orden parcial de calificadores-cv por el orden de restricciones incrementales. Puede decirse que el tipo es más o menos calificado-cv que:

  • no-calificado < const
  • no-calificado < volatile
  • no-calificado < const volatile
  • const < const volatile
  • volatile < const volatile

Las referencias y punteros a tipos calificados-cv pueden ser convertidos implícitamente a referencias y punteros a tipos más calificados-cv. En particular, las siguientes conversiones se permiten:

  • referencia/puntero a un tipo no-calificado puede convertirse a una referencia/puntero a const
  • referencia/puntero a un tipo no-calificado puede convertirse a una referencia/puntero a volatile
  • referencia/puntero a un tipo no-calificado puede convertirse a una referencia/puntero a const volatile
  • referencia/puntero a un tipo const puede convertirse a una referencia/puntero a const volatile
  • referencia/puntero a un tipo volatile puede convertirse a una referencia/puntero a const volatile
Nota: Se imponen restricciones adicionales en punteros de niveles múltiples.

Para convertir una referencia o un puntero a un tipo calificado-cv a una referencia, o un puntero a un tipo menos calificado-cv, se tiene que usar const_cast.

[editar] Palabras clave

const, volatile, mutable

[editar] Notas

El calificador const usado en una declaración de una variable no local, no volátil, no-plantilla (desde C++14), no-inline (desde C++17) que no está declarada como extern le da enlace interno. Esto es diferente de C, donde las variables en ámbito de archivo tienen enlace externo.

La gramática del lenguage C++ trata a mutable como un especificador de clase de almacenamiento, en lugar de un calificador de tipo, pero no afecta la clase de almacenamiento o el enlace.

[editar] Ejemplo

int main()
{
    int n1 = 0;           // objeto no-const
    const int n2 = 0;     // objeto const
    int const n3 = 0;     // objeto const (lo mismo que n2)
    volatile int n4 = 0;  // objeto volátil
    const struct
    {
        int n1;
        mutable int n2;
    } x = {0, 0};      // objeto const con miembro mutable
 
    n1 = 1; // de acuerdo, objeto modificable
//  n2 = 2; // ERROR: objeto no modificable
    n4 = 3; // de acuerdo, se trata como un efecto secundario
//  x.n1 = 4; // ERROR: miembro de un objeto const es const
    x.n2 = 4; // de acuerdo, miembro mutable de un objeto const no es const
 
    const int& r1 = n1; // referencia a const vinculada a objeto no-const
//  r1 = 2; // ERROR: intento de modificar mediante referencia a const
    const_cast<int&>(r1) = 2; // de acuerdo, modifica objeto no-const n1
 
    const int& r2 = n2; // referencia a const vinculada a objeto const
//  r2 = 2; // ERROR: intento de modificar mediante referencia a const
//  const_cast<int&>(r2) = 2; // comportamiento indefinido: intento de modificar objeto const n2
}

Salida:

# código de máquina típico producido en una plataforma x86_64
# (solamente el código que contribuye a los efectos secundarios se emite)
main:
    movl    $0, -4(%rsp) # volatile int n4 = 0;
    movl    $3, -4(%rsp) # n4 = 3;
    xorl    %eax, %eax   # return 0 (implícito)
    ret

[editar] Véase también

Documentación de C para calificador const
Documentación de C para calificador volatile