const
andvolatile
) type qualifiersGeneral topics | ||||
Flow control | ||||
Conditional execution statements | ||||
Iteration statements (loops) | ||||
Jump statements | ||||
Functions | ||||
Function declaration | ||||
Lambda function expression | ||||
inline specifier | ||||
Dynamic exception specifications(until C++17*) | ||||
noexcept specifier(C++11) | ||||
Exceptions | ||||
Namespaces | ||||
Types | ||||
Specifiers | ||||
Storage duration specifiers | ||||
Initialization | ||||
Expressions | ||||||||||||||||
Alternative representations | ||||||||||||||||
Literals | ||||||||||||||||
Boolean -Integer -Floating-point | ||||||||||||||||
Character -String -nullptr(C++11) | ||||||||||||||||
User-defined(C++11) | ||||||||||||||||
Utilities | ||||||||||||||||
Attributes(C++11) | ||||||||||||||||
Types | ||||||||||||||||
typedef declaration | ||||||||||||||||
Type alias declaration(C++11) | ||||||||||||||||
Casts | ||||||||||||||||
Memory allocation | ||||||||||||||||
Classes | ||||||||||||||||
Class-specific function properties | ||||||||||||||||
| ||||||||||||||||
Special member functions | ||||||||||||||||
Templates | ||||||||||||||||
Miscellaneous | ||||||||||||||||
|
Appear in any type specifier, includingdecl-specifier-seq ofdeclaration grammar, to specify constness or volatility of the object being declared or of the type being named.
Contents |
Any (possiblyincomplete) type other thanfunction type orreference type is a type in a group of the following four distinct but related types:
These four types in the same group have the samerepresentation andalignment requirements.
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 ofdecl-specifier-seq or part of adeclarator in adeclaration, or part oftype-id in anew-expression) determine the constness or volatility of the object, as follows:
Each cv-qualifier (const andvolatile) can appear at most once in any cv-qualifier sequence. For example,constconst andvolatileconstvolatile are not valid cv-qualifier sequences.
mutable
specifierMay appear in the declaration of a non-staticclass members of non-reference non-const type:
class X{ mutableconstint* p;// OK mutableint*const q;// ill-formed mutableint& r;// ill-formed};
mutable is used to specify 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).
class ThreadsafeCounter{ mutablestd::mutex m;// The "M&M rule": mutable and mutex go togetherint 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;}};
There is partial ordering of cv-qualifiers by the order of increasing restrictions. The type can be saidmore orless cv-qualified than:
References and pointers to cv-qualified types can be implicitly converted to references and pointers to more cv-qualified types, seequalification conversions for details.
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.
Theconst qualifier used on a declaration of a non-local non-volatilenon-template(since C++14)non-inline(since C++17) variable that is not declaredextern gives itinternal linkage. This is different from C where const file scope variables have external linkage.
The C++ language grammar treatsmutable as astorage-class-specifier, rather than a type qualifier, but it does not affect storage class or linkage.
Some uses of volatile are deprecated:
| (since C++20) |
#include <cstdlib> int main(){int n1=0;// non-const objectconstint n2=0;// const objectintconst n3=0;// const object (same as n2)volatileint n4=0;// volatile object conststruct{int n1; mutableint 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 constint& r1= n1;// reference to const bound to non-const object// r1 = 2; // error: attempt to modify through reference to constconst_cast<int&>(r1)=2;// OK: modifies non-const object n1 constint& 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 [](...){}(n3, n4, x, r2);// see also: [[maybe_unused]] std::system("g++ -O3 -Wa,-adhln ./main.cpp");// may issue asm on POSIX systems}
Possible 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
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
CWG 1428 | C++98 | the definition of 'const object' was based on declaration | based on object type |
CWG 1528 | C++98 | there was no requirement on the number of occurrences of each cv-qualifier in the same cv-qualifier sequence | at most once for each cv-qualifier |
CWG 1799 | C++98 | mutable could be applied to data members not declared const, but the members' types may still be const-qualified | cannot applymutable to data members of const-qualified types |
C documentation forconst qualifier | |
C documentation forvolatile qualifier |