cv
(
const
and
volatile
)
type qualifiers
Aparecen en cualquier especificador de tipo, incluyendo decl-specifier-seq de la gramática de declaraciones , para especificar constancia o volatilidad del objeto siendo declarado o del tipo siendo nombrado.
- const - define que el tipo es constante .
- volatile - define que el tipo es volátil .
Contenidos |
Explicación
Cualquier tipo (posiblemente incompleto ) que no sea function type o reference type es un tipo en un grupo de los siguientes cuatro tipos distintos pero relacionados:
- Una versión cv-unqualified .
- Una versión const-qualified .
- Una versión volatile-qualified .
- Una versión const-volatile-qualified .
Estos cuatro tipos en el mismo grupo tienen los mismos requisitos de representación y requisitos de alineación .
Tipos de array se consideran que tienen la misma calificación cv que sus tipos de elemento.
Objetos const y volatile
Cuando un objeto es creado por primera vez, los calificadores cv utilizados (que podrían ser parte de decl-specifier-seq o parte de un declarator en una declaración , o parte de type-id en una expresión new ) determinan la constancia o volatilidad del objeto, de la siguiente manera:
- Un objeto const es
-
- un objeto cuyo tipo está calificado como const, o
- un subobjeto no- mutable de un objeto const.
- Dicho objeto no puede ser modificado: el intento de hacerlo directamente es un error en tiempo de compilación, y el intento de hacerlo indirectamente (por ejemplo, modificando el objeto const a través de una referencia o puntero a tipo no-const) resulta en comportamiento indefinido.
- Un objeto volátil es
-
- un objeto cuyo tipo está calificado como volátil,
- un subobjeto de un objeto volátil, o
- un mutable subobjeto de un objeto const-volátil.
- Cada acceso (operación de lectura o escritura, llamada a función miembro, etc.) realizado a través de una expresión glvalue de tipo calificado como volátil se trata como un efecto secundario visible para los propósitos de optimización (es decir, dentro de un único hilo de ejecución, los accesos volátiles no pueden ser optimizados ni reordenados con otro efecto secundario visible que esté secuenciado-antes o secuenciado-después del acceso volátil. Esto hace que los objetos volátiles sean adecuados para comunicación con un manejador de señales , pero no con otro hilo de ejecución, véase std::memory_order ). Cualquier intento de acceder a un objeto volátil a través de un glvalue de tipo no volátil (por ejemplo, a través de una referencia o puntero a tipo no volátil) resulta en comportamiento indefinido.
- Un objeto const volatile es
- Se comporta tanto como un objeto const como un objeto volátil.
Cada calificador cv ( const y volatile ) puede aparecer como máximo una vez en cualquier secuencia de calificadores cv. Por ejemplo, const const y volatile const volatile no son secuencias válidas de calificadores cv.
mutable
especificador
- mutable - permite la modificación del miembro de clase declarado como mutable incluso si el objeto contenedor está declarado como const (es decir, el miembro de clase es mutable).
Puede aparecer en la declaración de un miembro de clase no estático de tipo no constante y no referencia:
class X { mutable const int* p; // CORRECTO mutable int* const q; // incorrecto mutable int& r; // incorrecto };
mutable se utiliza para especificar que el miembro no afecta el estado externamente visible de la clase (como se usa frecuentemente para mutexes, memo caches, evaluación diferida e instrumentación de acceso).
class ThreadsafeCounter { mutable std::mutex m; // La regla "M&M": mutable y mutex van juntos int data = 0; public: int get() const { std::lock_guard<std::mutex> lk(m); return data; } void inc() { std::lock_guard<std::mutex> lk(m); ++data; } };
Conversiones
Existe un ordenamiento parcial de calificadores cv por el orden de restricciones crecientes. Se puede decir que el tipo está más o menos calificado cv que:
- sin calificación < const
- sin calificación < volatile
- sin calificación < const volatile
- const < const volatile
- volatile < const volatile
Las referencias y punteros a tipos calificados cv pueden convertirse implícitamente a referencias y punteros a tipos más calificados cv, consulte conversiones de calificación para más detalles.
Para convertir una referencia o un puntero a un tipo calificado con cv a una referencia o puntero a un tipo con menos calificación cv,
const_cast
debe ser utilizado.
Notas
El calificador const utilizado en una declaración de una variable no local no volátil no template (desde C++14) no inline (desde C++17) que no está declarada extern le otorga enlace interno . Esto es diferente de C donde las variables const de ámbito de archivo tienen enlace externo.
La gramática del lenguaje C++ trata a mutable como un storage-class-specifier , en lugar de un calificador de tipo, pero no afecta la clase de almacenamiento o el enlace.
|
Algunos usos de volatile están obsoletos:
|
(desde C++20) |
Palabras clave
Ejemplo
#include <cstdlib> int main() { int n1 = 0; // objeto no constante const int n2 = 0; // objeto constante int const n3 = 0; // objeto constante (igual que n2) volatile int n4 = 0; // objeto volátil const struct { int n1; mutable int n2; } x = {0, 0}; // objeto constante con miembro mutable n1 = 1; // OK: objeto modificable // n2 = 2; // error: objeto no modificable n4 = 3; // OK: tratado como efecto secundario // x.n1 = 4; // error: miembro de un objeto constante es constante x.n2 = 4; // OK: miembro mutable de un objeto constante no es constante const int& r1 = n1; // referencia a constante vinculada a objeto no constante // r1 = 2; // error: intento de modificar mediante referencia a constante const_cast<int&>(r1) = 2; // OK: modifica el objeto no constante n1 const int& r2 = n2; // referencia a constante vinculada a objeto constante // r2 = 2; // error: intento de modificar mediante referencia a constante // const_cast<int&>(r2) = 2; // comportamiento indefinido: intento de modificar objeto constante n2 [](...){}(n3, n4, x, r2); // ver también: [[maybe_unused]] std::system("g++ -O3 -Wa,-adhln ./main.cpp"); // puede emitir código ensamblador en sistemas POSIX }
Salida posible:
# typical machine code produced on an x86_64 platform
# (only the code that contributes to observable side-effects is emitted)
main:
movl $0, -4(%rsp) # volatile int n4 = 0;
movl $3, -4(%rsp) # n4 = 3;
xorl %eax, %eax # return 0 (implicit)
ret
Informes de defectos
Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares publicados anteriormente de C++.
| DR | Se aplica a | Comportamiento publicado | Comportamiento correcto |
|---|---|---|---|
| CWG 1428 | C++98 | la definición de 'objeto const' se basaba en la declaración | basada en el tipo de objeto |
| CWG 1528 | C++98 |
no existía requisito sobre el número de apariciones
de cada calificador cv en la misma secuencia de calificadores cv |
como máximo una vez para
cada calificador cv |
| CWG 1799 | C++98 |
mutable
podía aplicarse a miembros de datos no declarados
const , pero los tipos de los miembros aún podían estar calificados como const |
no se puede aplicar
mutable
a miembros de
datos de tipos calificados como const |
Véase también
|
Documentación de C
para
const
qualifier
|
|
|
Documentación de C
para
volatile
qualifier
|