auto, scope and lifetime
The name of a variable declared inside curly braces works only up to the closing brace. Outside them, the name is unknown:
#include <iostream>
int main() {
int total = 0;
{
int bonus = 10;
total = total + bonus;
}
std::cout << total + bonus << '\n'; // ✗
}error: use of undeclared identifier 'bonus'The part of a program where a variable's name can be used is its scope. It starts at the declaration and ends at the closing brace of the block, the code between a pair of curly braces. A function body is a block too, so variables with the same name in different functions are different variables.
A variable declared outside every function is global. Its name is visible from the declaration to the end of the file, and the variable lives until the program ends.
Hiding a name
An inner block may declare a variable with the same name as an outer one. This is a new variable: until the end of the block, the name denotes it, and the outer one is hidden. Such shadowing ends at the closing brace, and the outer variable is visible again with its old value:
#include <iostream>
int main() {
int score = 5;
{
int score = 100;
std::cout << score << '\n'; // 100
}
std::cout << score << '\n'; // 5
}Lifetime
A variable's lifetime is the time during which it exists in memory. Scope belongs to a name in the program text, while lifetime belongs to the variable itself at run time. An ordinary variable inside a function is created when execution reaches its declaration and destroyed at the end of its block. On the next call to the function, it is created again.
A variable marked static lives until the program ends. It is initialized once, not on every call, and keeps its value between calls:
#include <iostream>
void visit() {
static int visits = 0;
int steps = 0;
visits = visits + 1;
steps = steps + 1;
std::cout << visits << ' ' << steps << '\n';
}
int main() {
visit(); // 1 1
visit(); // 2 1
visit(); // 3 1
}steps starts from 0 on every call, while visits keeps counting. static changes only the lifetime: visits is still visible only inside visit.
Type from the initial value
auto can stand in place of a type, and then the compiler deduces the type from the initial value. It matches the literal's type: auto count = 10; gives an int, and auto price = 2.5; a double. For auto ratio = 2.5f;, it is a float. That is why auto does not work without an initial value: auto total; does not compile.
Common mistake
A variable for a fractional sum is declared with auto and the initial value 0:
#include <iostream>
int main() {
auto total = 0; // ✗
total = total + 2.5;
std::cout << total << '\n'; // 2
}The literal 0 is an int, so total gets the type int too. The assignment turns 0 + 2.5 into 2, and the compiler stays silent. The fix is a literal of the right type: auto total = 0.0;.