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
usingnamespace std;
int x(100);
int out1()
{
return x + 1;
}
int out2()
{
return x + 2;
}
int main()
{
cout << out1() << "\n" << out2() << endl;
}
You've put the value of BASE inside {...} curly braces......
What did you do this, why not: constint 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) & constint 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!
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) {
constint yen_in_dollar = 120;
return (dollars * yen_in_dollar);
}
void print() {
constint yen_in_dollar = 120;
constint 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) {
constint yen_in_dollar = 120;
return (dollars * yen_in_dollar);
}
void print() {
constint yen_in_dollar = 102;//Oops, I made a mistake and I didn't notice!
constint 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.
int x(1) & constint 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)
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.
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 ;)