Download presentation
Presentation is loading. Please wait.
1
The const keyword: keeping data safe
2
Outline In this lesson, we will:
Understand the need to protect stored values Examine constant local variables and constant references Examine constant parameters and constant reference parameters See various applications Understand the software engineering principle behind this keyword
3
Programming practice Up to this point, we have looked most at principles of programming We have seen the structured programming theorem This is responsible for our ability to write software projects on the scale we see today By restricting flow control to conditional statements and looping statements, code maintainability is greatly increased We will now look at another software engineering tool that can be used to reduce both development and maintenance time and costs
4
Software problem Some variables or parameters contain values not meant to be changed: int main() { double pi{ }; // do something... if ( pi > x ) { // Do something... } else if ( pi = x ) { // Do something else... } What happened here?
5
Local constants To prevent anyone from assigning to a local variable after it has been initialized, that variable can be declared constant: typename const IDENTIFIER{value}; During the software design phase, all local variables should be inspected to determine which are truly variable, and which should be constant Indicating that a local variable is constant can allow for optimizations by the compiler Constants are identified using all caps s This ensures other developers immediately differentiate between constants and variables You can also use const typename IDENTIFIER{value};
6
Local constants It is a compile-time error if a local constant is initialized: example.cpp: In function 'int main()': example.cpp:6:12: error: uninitialized const 'SAMPLE COUNT' int const SAMPLE COUNT; ^ It is a compile-time error to ever assign to a local constant: example.cpp:7:15: error: assignment of read-only variable 'SAMPLE_COUNT' SAMPLE COUNT = 64; A local constant is also referred to as a “read-only variable”
7
Mathematical constants
Mathematical and physical constants are declared as such: int main() { double const PI{ }; double const TWO_PI{2.0*PI}; double const PI_BY_2{PI/2.0}; double const HC{ e-25}; // Jm double const AVOGADRO{ e23}; // 1/mol // Do something... }
8
Array capacities Hard coding any number other that 0 or 1 can lead to issues: int main() { int temperatures[15]{}; for ( std::size_t k{0}; k < 15; ++k ) { temperatures[k] = get_temperature(); wait( 1000 ); // Wait 1000 ms = 1 s } // Do something... int initial_time{15}; double average{0.0}; average += temperatures[k]; average /= 15;
9
Array capacities Suppose we want to change the array size from 15 to 32 A global search-and-replace will also replace the initial time Additionally, it should not be possible to change the array capacity once it is initialized
10
Array capacities Having a local constant with the capacity helps
int main() { std::size_t const TEMP_CAPACITY{15}; int temperatures[TEMP_CAPACITY]{}; for ( std::size_t k{0}; k < TEMP_CAPACITY; ++k ) { temperatures[k] = get_temperature(); wait( 1000 ); // Wait 1000 ms = 1 s } // Do something... int initial_time{15}; double average{0.0}; average += temperatures[k]; average /= TEMP_CAPACITY;
11
Constant arrays An array can also be declared constant:
None of the entries can be changed after initialization std::size_t const NPQE_CAPACITY{10}; double const NEXT_POINT_QUAD_EXTRAP[NPQE_CAPACITY]{ 54.0/60.0, 30.0/60.0, 11.0/60.0, -3.0/60.0, -12.0/60.0, -16.0/60.0, -15.0/60.0, -9.0/60.0, 2.0/60.0, 18.0/60.0 };
12
Constant references References can also be declared constant:
double variable{32}; double const &ALIAS{variable}; variable = 42; // correct the value ALIAS = 91; // can't touch that... This prevents any future editor of this code from accidentally changing the value example.cpp: In function 'int main()': example.cpp:9:8: error: assignment of read-only reference 'alias' alias = 91; ^
13
Constant references Also, you cannot assign a local constant to a non-constant alias double const VARIABLE{42}; double &alias{VARIABLE}; alias = 32; // let us override the 'const' keyword // by assigning to the alias The language prevents you, and while the error message is opaque, it points you to the problem: example.cpp: In function 'int main()': example.cpp:7:21: error: invalid initialization of non-const reference of type 'int&' from an rvalue of type '<brace-enclosed initializer list>'
14
Constant references Local constants can only initialize constant references: double const VARIABLE{42}; double const &ALIAS{VARIABLE};
15
Constant parameters It is also possible to declare a parameter constant double average( double const array[], std::size_t const capacity ) { double average{0.0}; for ( std::size_t k{0}; k < capacity; ++k ) { average += array[k]; } return average/capacity; This prevents any future editor of this code from accidentally changing the value There is no reason that either the entries of the array nor the capacity of the array be changed by a function calculating the average
16
Constant parameters While this is a simple function, if a future editor were to accidentally try to change the entries of the array or the capacity, they would get a compile-time error: double average( double const array[], std::size_t const capacity ) { double average{0.0}; for ( std::size_t k{0}; k < capacity; ++k ) { average += array[k]; } average /= capacity; // Subtract off the average array[k] -= average; return average;
17
Constant parameters In this case, the error message is a little opaque, but it points to the problem You will understand this error message in a few weeks example.cpp: In function 'double average(const double*, std::size_t)': example.cpp:17:18: error: assignment of read-only location '*(array + ((sizetype)(k * 8ul)))' array[k] -= average; ^
18
Constant reference parameters
Recall our 3-dimensional vector example: bool is_unit( vector_3d_t const &v ); bool is_unit( vector_3d_t const &v ) { return ( norm( v ) == 1.0 ); } Benefits: The vector is not copied The function cannot change the member variables
19
Constant reference parameters
There is a problem with this implementation: A normalized vector should be a unit vector: int main() { vector_3d_t v{0.532, 0.723, 0.299}; std::cout.precision( 16 ); std::cout << is_unit( v ) << std::endl; normalize( v ); std::cout << norm( v ) << std::endl; return 0; } false Output:
20
Constant reference parameters
A better implementation: bool is_unit( vector_3d_t const &v ); bool is_unit( vector_3d_t const &v ) { return ( std::abs( norm( v ) ) < 5e-16 ); } We can also update the function norm(...) as well as others: double norm( vector_3d_t const &v ); double norm( vector_3d_t const &v ) { return std::sqrt( v.x*v.x + v.y*v.y + v.z*v.z );
21
Constant reference parameters
Recall our bank account example: void deposit( bank_account_t &acct, unsigned long amount ); bool is_in_overdraft( bank_account_t &acct ); The first should change the amount in the account It should not be const Question: should the amount be const? For safety, probably yes… The second is simply asking a question: Is the account in overdraft? There is no reason this should change the account
22
Constant reference parameters
A programmer attempting to introduce service charges will result in compile-time errors void deposit( bank_account_t &acct, unsigned long const amount ) { // A service charge of $1.00 for deposits greater than // $1 million if ( amount > ) { amount -= 100; } acct.balance += amount; bool is_in_overdraft( bank_account_t const &acct ) { // A service charge of $0.10 for asking... account.balance -= 10; return (acct.balance < 0);
23
Constant reference parameters
The error messages are quite clear: example.cpp: In function 'void deposit(bank_account_t&, long unsigned int)': example.cpp:19:10: error: assignment of read-only parameter 'amount' amount -= 100; ^ 'bool is_in_overdraft(const bank_account_t&)': example.cpp:26:15: error: assignment of member 'bank_account_t::balance' in read-only object acct.balance -= 10;
24
Constant reference parameters
Suppose you try to pass a constant reference parameter to another function where the reference parameter is not declared const? bool is_in_overdraft( bank_account_t const &acct ) { // A $0.01 fee for asking... withdraw( acct, 1 ); return (acct.balance < 0); } Again, the compiler won’t let you: example.cpp: In function 'bool is_in_overdraft(const bank_account_t&)': example.cpp:29:20: error: invalid initialization of reference of type 'bank_account_t&' from expression of type 'const bank_account_t' ^ example.cpp:22:6: error: in passing argument 1 of 'void withdraw(bank_account_t&, long unsigned int)' void withdraw( bank_account_t &acct,
25
Why not remove const? If the const keyword keeps you from doing something you think you want to do, it’s up to you to revisit the specification: Why was it required that the parameter be declared const? Have the circumstances changed since the specification was written? Who is responsible for the specification, and what is their opinion?
26
Synopsis A perfectly functioning program that uses const will still be a perfectly functioning program if all instances of const are removed A perfectly function program that uses const correctly, however, is less likely to have errors introduced by subsequent programmers A program design that uses const is less likely to have programmers go down the wrong path during development than one that does not use const All const says to the programmer or compiler: This variable, parameter or reference should not be changed
27
Summary Following this lesson, you now:
Know that the const keyword is there for one reason only: To prevent you from assigning to a variable or parameter that must not be changed Understand that anything declared const must be initialized Know the relationships: local variable ↔ local constant reference variable ↔ constant reference parameter ↔ constant parameter reference parameter ↔ constant reference parameter
28
References [1] [2] [3]
29
Colophon These slides were prepared using the Georgia typeface. Mathematical equations use Times New Roman, and source code is presented using Consolas. The photographs of lilacs in bloom appearing on the title slide and accenting the top of each other slide were taken at the Royal Botanical Gardens on May 27, 2018 by Douglas Wilhelm Harder. Please see for more information.
30
Disclaimer These slides are provided for the ece 150 Fundamentals of Programming course taught at the University of Waterloo. The material in it reflects the authors’ best judgment in light of the information available to them at the time of preparation. Any reliance on these course slides by any party for any other purpose are the responsibility of such parties. The authors accept no responsibility for damages, if any, suffered by any party as a result of decisions made or actions based on these course slides for any other purpose than that for which it was intended.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.