Constants
C++ defines a complete set of methods for defining read-only quantities. Variables modified by const are read-only quantities. The compiler performs conflict checks at compile time to prevent modifications to read-only quantities and may also perform some optimizations.
In general, you should use const to modify variables and parameters as much as possible to improve code robustness.
const Type Qualifier
Constants
Variables modified by const cannot have their values changed after initialization.
1 2 3 | |
Constant References and Constant Pointers
Both constant references and constant pointers restrict modification of the pointed-to value.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
Additionally, it's important to distinguish between a constant pointer (const t*) and a pointer constant (t* const). For example, the following declarations:
1 2 3 4 5 6 7 8 | |
Using const to qualify parameter types in function parameters can prevent variables from being accidentally modified and increase code readability.
1 2 3 4 | |
const Member Functions
Member functions qualified with const within a type can be used to restrict modification of members.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | |
Constant Expression constexpr (C++11)
A constant expression is an expression whose result can be computed at compile time. constexpr requires the compiler to be able to evaluate the value of a function or variable at compile time.
Compile-time computation allows for better optimization, such as hardcoding results into assembly and eliminating runtime computation overhead. Unlike optimizations brought by const, when a variable modified by constexpr meets the conditions of a constant expression, it forces the compiler to compute the result at compile time rather than runtime.
A more intuitive understanding is to think of const as 'read-only' and constexpr as 'immutable'.
1 2 3 4 5 6 7 8 | |
The following example clearly illustrates the difference between const and constexpr. The code uses recursion to compute the Fibonacci sequence and outputs using control flow.
Implementation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | |
Possible assembly code after compilation (using Compiler Explorer, Clang 19)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | |
The constexpr-modified fib0 function is called with a constant argument at its only call site, causing the entire function to run only at compile time. Since the function has no runtime execution, the compiler determines that no assembly code needs to be generated.
Also note in the assembly that v0 has no initialization code. In the code that calls cout to output v0, v0 has already been replaced by the final computed result, indicating the variable value was computed at compile time, optimizing away runtime computation.
In contrast, the initialization of v1 is still a normal recursive call to fib1.
Therefore, constexpr can be used to replace macro-defined constants, avoiding the risks of macro definitions.
In algorithmic problems, constexpr can be used to store variables with small data sizes to eliminate corresponding runtime computation overhead. It is particularly common in the "table lookup" technique, using constexpr-modified containers like arrays to store answers.
Excessive compile-time computation will cause compilation errors
The compiler limits the overhead of compile-time computation. If the computation is too large, compilation will fail, and const should be considered instead.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | |
Compilation error given by Clang when using constexpr
1 2 3 4 5 6 7 8 9 10 | |
References
本页面最近更新:,更新历史
发现错误?想一起完善? 在 GitHub 上编辑此页!
本页面贡献者:OI-wiki
本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用