3. const and constexpr #

Created Thursday 26 December 2019

**Constant variables: **It’s weird, we are apparently interested making variables, whose the value is unchangeable. This is not the case.

Syntax

const int p = 2; // instant initialization is necessary - results in error

How does it works? In the symbol table, we have many fields like**:**

What does it do? const means read only for the variable, this is what is put in the symbol table. They cannot be changes after they have been declarized.

Important concepts #

int x = 2;
const int *p = &x;
x = 3;	// can change memory- OK
*p = 23; // error - change not allowed at using p
cout << *p; // prints 3
int a = 12;
const int &k = a; // k is alias for integer constant(same as constant integer)
a++;       // OK
k++;       // error
cout << k; // 13

**Reason: **When we made a const int &, we copied the address to a new tuple in the symbol table, changed the name to k, and made the type qualifier as const. This makes it look as if k is a const variable. Hence no operations are allowed **through **it.

Questions #

**Q) **Does the compiler allow const int* p = int*(and vice-versa), why? **A) *const int* p = int*, yes. Because const just makes a promise of immutability for a new variable, i.e we cannot restrict existing variables. In this case, we’ll not be able to change the contents using the ‘p’. In other words, making a promise is allowed. The converse, i.e int * = const int, no. // i.e this is not allowed. Because this will actually break the promise, i.e breaking a promise is not allowed.

Q) Is this allowed?

int i = 10, j = 12;
int const *p = &i; // change not allowed through p
p = &j; // but p can itself be changed.

A) Yes, valid because const restricts writing at the address. But changing the address itself is allowed, because we never promised about it. In step 3, we should read from right to left, for the declaration, "I am p, i will not make change at the address I store, **but **I can change the address itself.

Note

int * const p = &i; // p is a pointer(which we won't change) to an integer
// Here p itself is unchangeable
// But we can change the value at p.
int const * const p = &i; // Neither address nor value at address changeable.

Concise.

  1. Only paths(through) are blocked. Storage can never be tagged constant.
  2. We can make promises of immutability, but not do something that will break them. Remember that the compiler does not track memory, it only has the symbol table.
  3. Read the declaration from right to left.(One const can only put one restriction).
  4. Use east const style.
  5. const data_type and data_type const is the same. For any case. Even if you use & and *.

**Advantages: **

  1. We used reference to decrease the argument copy overhead. by avoiding a pointer. By using const data_type, we protect it further. **Hence **we find const int at many places in headers like iostream and STL.
  2. Point 1 helps immensely in funtion calling.

constexpr #

Consider the following code - here there’s no optimizations that the compiler can make to age. This is because its value is known only at run-time.

int ageInput;
cin >> ageInput;
const age = ageInput; // age cannot be changed

But if we are sure of a value at compile time, then use constexpr

int ageInput;
cin >> ageInput;
constexpr age = ageInput; // age cannot change
// compiler optimization possible

Note: