The use of "const"?

This from the learncpp website regarding the use of "const":
"Normal local variables are subject to local scoping rules, meaning they can only be accessed in the block in which they are declared. If you needed to use the same constant in different blocks, you’d have to declare it in each place you need it (which is both redundant and puts your code at risk of mistakes)."

I don’t understand this!
If i first declare (example below) a normal local variable, that value of x is seen by all following code blocks. No need for "const".
Could someone please give me a simple code example of this? So, first a "broken" version which just uses good ol’ normal local variables, and then the fixed version using const?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 using namespace std;

int x(100);

int out1()
{
	return x + 1;
}

int out2()
{
	return x + 2;
}

int main()
{
	cout << out1() << "\n" << out2() << endl;
}
I don’t understand this!
They mean that you shall create the constant within the global not local scope. It is okay since there is no risk of somehow changed value.

No need for "const".
Make a variable const when you don't want it to be changed. Hence line 3 would be okay as
const int x(100);
Your x is not a local variable! It is a global variable.

If you needed to use the same constant

"Same constant", not "same variable".

What your example essentially has, is:
1
2
int out1() { return 100 + 1; }
int out2() { return 100 + 2; }

The magic value 100 repeats in many places and it is unclear what it represents. Changing it is a major search-and-replace. Tedious and error-prone.

The C programmers did notice that the preprocessor can do search-and-replace on the fly:
1
2
3
#define BASE 100;
int out1() { return BASE + 1; }
int out2() { return BASE + 2; }

The code is now more expressive and easier to maintain, but the preprocessor macros are tricky. Therefore, the C++ did provide the const:
1
2
3
const int BASE {100};
int out1() { return BASE + 1; }
int out2() { return BASE + 2; }

Now we know for certain that the BASE in an int and thanks to const it cannot be changed accidentally.
Thanks!

A couple of questions:

You've put the value of BASE inside {...} curly braces......

What did you do this, why not: const int BASE(100);?

From my original post is the quote
"Normal local variables are subject to local scoping rules, meaning they can only be accessed in the block in which they are declared. If you needed to use the same constant in different blocks, you’d have to declare it in each place you need it (which is both redundant and puts your code at risk of mistakes)."


Did you cover that in your answer?

Aren't int BASE(100) & const int BASE(100) interchangable, apart from the fact that const protects the constant from being changed later?

You said:

What your example essentially has, is:
1
2
int out1() { return 100 + 1; }
int out2() { return 100 + 2; }


The magic value 100 repeats in many places and it is unclear what it represents. Changing it is a major search-and-replace. Tedious and error-prone.


But my magic number isn't magic is it? I can change it globally at any time by re-assigning the value of x at line 3. That's why i don't understand the comment from learncpp posted above!

And.......sorry for being so freakin' dumb!



Last edited on
Normal local variables are subject to local scoping rules, meaning they can only be accessed in the block in which they are declared.


1
2
3
4
5
6
7
8
9
10
11
void foo() {

	int i = 0;

}

void bar() {

	i = 0;//error

}


or

1
2
3
4
5
6
7
8
void foo() {

	{
		int i = 0;
	}

	i = 0;//error
}


Whether or not an object has been declared const has no bearing on it's scope or lifetime.

If you needed to use the same constant in different blocks, you’d have to declare it in each place you need it (which is both redundant and puts your code at risk of mistakes).


For lack of a better example, what they meant with this is the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int calculate_dollars_to_yen(int dollars) {

	const int yen_in_dollar = 120;

	return (dollars * yen_in_dollar);

}

void print() {

	const int yen_in_dollar = 120;
	const int num_dollars = 2;

	std::cout << "There are " << yen_in_dollar << " yen in one dollar." << std::endl;
	std::cout << "Therefore, there are " << calculate_dollars_to_yen(num_dollars) << " yen in " << num_dollars << " dollars." << std::endl;

}


Both of these two functions need access to yen_in_dollar. One makes a conversion using yen_in_dollar and the other prints yen_in_dollar.
As you can see, yen_in_dollar has been declared and defined twice, once in each function. They are local constants. It's redundant because you shouldn't have to declare and define the same thing twice, and it could introduce mistakes because of human error :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int calculate_dollars_to_yen(int dollars) {

	const int yen_in_dollar = 120;

	return (dollars * yen_in_dollar);

}

void print() {

	const int yen_in_dollar = 102;//Oops, I made a mistake and I didn't notice!
	const int num_dollars = 2;

	std::cout << "There are " << yen_in_dollar << " yen in one dollar." << std::endl;
	std::cout << "Therefore, there are " << calculate_dollars_to_yen(num_dollars) << " yen in " << num_dollars << " dollars." << std::endl;

}


Note that yen_in_dollar in print()'s scope has "accidentally" been defined incorrectly, confusing anyone who reads print()'s output. This could have been mitigated by simply declaring and defining a single constant only once in a scope where both functions can see it, such as in the global scope in this case.
Last edited on
Thanks!

Is this statement true or false?:

int x(1) & const int x(1) are interchangable, apart from the fact that const protects x from being changed later?

If not, could you give an extremely simple example of a program that works using const but not without? (obviously you could write a program that broke because x {of the non-const variety} got re-assigned, but i understand that point)
Last edited on
It's context sensitive. The const keyword indicates that an object cannot be modified. Therefore, you'd use a constant when representing something you either know won't change or don't want changed.

1
2
3
4
5
6
7
8
int main() {

	int num_elements = 10;

	int element[num_elements] = {0};//error

	return 0;
}


num_elements is not constant. You cannot have a typical array like this with a variable number of elements (dynamic memory is another topic), so you'll get an error.

In the case of the example you provided:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int x(100);

int out1()
{
	return x + 1;
}

int out2()
{
	return x + 2;
}

int main()
{
	cout << out1() << "\n" << out2() << endl;
}


In this specific example, it makes no real difference whether or not "x" is constant.
Last edited on
Warning: a const-reference only implies that the object cannot be changed through that particular reference to it, as the object can still change value if it is not actually constant.
OK, thanks, i didn't get to arrays yet, but it seems clear that const is mainly for protecting values that never change, like 24 hours in a day, 7 days a week, centimeters in a meter etc etc.
const is far more useful than that - const-correctness is most useful when writing const-member-functions, which guarantee that the state of an object will not change even if the object is not constant. const is a promise that says "I won't change this without your permission". Many languages do not have compiler-level support for this promise. In fact, const-correctness originated in C++ and was later added to C, not the other way around.

You will see it as being more useful when you get around to writing classes ;)
Last edited on
Topic archived. No new replies allowed.