cv (const and volatile) type qualifiers
Appear in any type specifier, including decl-specifier-seq of declaration grammar, to specify constness or volatility of the object being declared or of the type being named.
- const- defines that the type is constant.
- volatile- defines that the type is volatile.
- mutable- applies to non-static class members of non-reference non-const type and specifies that the member does not affect the externally visible state of the class (as often used for mutexes, memo caches, lazy evaluation, and access instrumentation).- mutablemembers of const class instances are modifiable. (Note: the C++ language grammar treats- mutableas a storage-class-specifier, but it does not affect storage class.)
 
| Contents | 
[edit] Explanation
For any type T (including incomplete types), other than function type or reference type, there are three more distinct types in the C++ type system: const-qualified T, volatile-qualified T, and const-volatile-qualified T.
- Note: array types are considered to have the same cv-qualification as their element types.
When an object is first created, the cv-qualifiers used (which could be part of decl-specifier-seq or part of a declarator in a declaration, or part of type-id in a new-expression) determine the constness or volatility of the object, as follows:
- const object - an object whose type is const-qualified, or a non-mutable subobject of a const object. Such object cannot be modified: attempt to do so directly is a compile-time error, and attempt to do so indirectly (e.g., by modifying the const object through a reference or pointer to non-const type) results in undefined behavior.
- volatile object - an object whose type is volatile-qualified, or a subobject of a volatile object, or a mutable subobject of a const-volatile object. Every access (read or write operation, member function call, etc.) made through a glvalue expression of volatile-qualified type is treated as a visible side-effect for the purposes of optimization (that is, within a single thread of execution, volatile accesses cannot be optimized out or reordered with another visible side effect that is sequenced-before or sequenced-after the volatile access. This makes volatile objects suitable for communication with a signal handler, but not with another thread of execution, see std::memory_order). Any attempt to refer to a volatile object through a non-volatile glvalue (e.g. through a reference or pointer to non-volatile type) results in undefined behavior.
- const volatile object - an object whose type is const-volatile-qualified, a non-mutable subobject of a const volatile object, a const subobject of a volatile object, or a non-mutable volatile subobject of a const object. Behaves as both a const object and as a volatile object.
| This section is incomplete Reason: should discuss more about the differences between cv-qualified objects and cv-qualified expressions | 
There is partial ordering of cv-qualifiers by the order of increasing restrictions. The type can be said more or less cv-qualified then:
-  unqualified < const
-  unqualified < volatile
-  unqualified < const volatile
-  const<const volatile
-  volatile<const volatile
 
-  unqualified < 
References and pointers to cv-qualified types may be implicitly converted to references and pointers to more cv-qualified types. In particular, the following conversions are allowed:
-  reference/pointer to unqualified type can be converted to reference/pointer to  const
-  reference/pointer to unqualified type can be converted to reference/pointer to volatile
-  reference/pointer to unqualified type can be converted to reference/pointer to const volatile
-  reference/pointer to consttype can be converted to reference/pointer toconst volatile
-  reference/pointer to volatiletype can be converted to reference/pointer toconst volatile
 
-  reference/pointer to unqualified type can be converted to reference/pointer to  
- Note: additional restrictions are imposed on multi-level pointers.
To convert a reference or a pointer to a cv-qualified type to a reference or pointer to a less cv-qualified type, const_cast must be used.
[edit] Keywords
[edit] Example
int main() { int n1 = 0; // non-const object const int n2 = 0; // const object int const n3 = 0; // const object (same as n2) volatile int n4 = 0; // volatile object const struct { int n1; mutable int n2; } x = {0, 0}; // const object with mutable member n1 = 1; // ok, modifiable object // n2 = 2; // error: non-modifiable object n4 = 3; // ok, treated as a side-effect // x.n1 = 4; // error: member of a const object is const x.n2 = 4; // ok, mutable member of a const object isn't const const int& r1 = n1; // reference to const bound to non-const object // r1 = 2; // error: attempt to modify through reference to const const_cast<int&>(r1) = 2; // ok, modifies non-const object n1 const int& r2 = n2; // reference to const bound to const object // r2 = 2; // error: attempt to modify through reference to const // const_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2 }
Output:
# 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[edit] See Also
| C documentation for const qualifier | |
| C documentation for volatile qualifier | 


