UPI Study › Courses › C++ Programming › Free lessons › Lesson 8.3 Free with a free account
Lifetime and Reach
C++ Programming · Chapter 8: FunctionsSection 8.3 · lesson 53 of 84video coming soon
← The C++ Standard LibraryNext lesson: How the Compiler Manages Variable Storage →
In this lesson
Where variables exist, and when they disappear.
- Tell where a name can be used from how long it lasts
- State the reach of locals, blocks and parameters
- Reach a hidden global, and avoid shadowing
- Keep a value between calls with a static local
Transcript
Everything said in the video, section by section (1,292 words). Read along, or search it.
Opening Question
Two Questions About Every Variable
Two different questions get asked about every variable, and confusing them causes a particular kind of bewilderment. One is about reach: from which parts of the program can this name be used? The other is about lifetime: for how long does the value survive? They usually answer together, and occasionally don't. That's exactly where the interesting cases are.
Definitions
Scope Versus Lifetime Compared
Scope is a question about the text of your program: over which region of the source does this name refer to this variable? Lifetime is a question about the running program: between which two moments does the value exist? An ordinary local is reachable from one block, and lives only while that block runs. That's the common case. A global is reachable from the whole file, and lives for the whole run: wide reach, long life, and a problem. And the interesting one is the static local: reachable from one block, but living for the whole run. Narrow reach, long life.
Block Scope
Names Reach to the Closing Brace
A variable declared inside a function is local to it. Its reach runs from the point of declaration to the closing brace of the block containing it. And every pair of braces starts a new block, not just the ones around a function body. Here, x reaches to the end of demo. Y, declared in a nested block, reaches only to that block's closing brace. Inside the nested block, both names are available. After it, y isn't known. The compiler says so. The rule reads in one direction only: an inner block sees the names around it, but no block sees names declared inside it. A loop's control variable follows the same rule. Declared in the loop heading, it reaches to the end of the loop and no further.
Parameters
A Parameter Is Just a Local
A parameter behaves in every respect like a variable declared at the top of the function body. It's created when the call begins, initialized from the argument supplied, and gone when the function returns. Here, count can be changed like any local. Report adds one and prints 8. But total, back in the caller, is still 7. The parameter's reach is the function body, and nothing outside can name it.
Global Variables
Globals and the Scope-Resolution Operator
A variable declared outside every function is global. Its name is available from the point of declaration to the end of the file, in every function that follows. It also lives for the entire run. Here, level is a global holding 10. Show prints 10, because there's no local of that name. Adjust declares its own local level, holding 5. Printing level gives 5, because the nearer name wins. Printing colon colon level gives 10. Those two colons are the scope-resolution operator. With nothing before them, they mean the one at the outermost level. It's the only way to reach a global that a local has hidden, and needing it is usually a sign a name is badly chosen.
Shadowing
When Inner Names Hide Outer Ones
When an inner declaration reuses a name from an enclosing scope, the inner one shadows the outer for the rest of its block. Here, total means three different things. The global holds 100. Tally's local holds 20. And a nested block's total holds 3. Adding one inside the nested block changes only the innermost total, to 4. After the block, total is 20, untouched. And colon colon total is 100, also untouched. This is legal, and a frequent source of the complaint, I changed it and nothing happened. By default, nothing tells you it happened. Most compilers will report it when asked, usually with dash W shadow. The better habit is simply not to reuse names across nested scopes.
Design Concerns
Why Global Variables Cause Trouble
A global works, and for a very small program it's convenient. The objections are about what happens as the program grows. Anything can change it. When the value is wrong, every function in the file is a suspect, so the search has no boundary. Pass it in as a parameter instead. The heading tells you nothing. A function that secretly reads or writes a global has inputs and outputs its declaration doesn't mention. Testing gets harder: a call's result depends on state left by earlier calls, so a test may pass alone and fail in company. And names collide: one short global name makes every local of that name a shadowing accident. But every objection is about a value that can change. A global marked const, like a tax rate or a maximum size, has none of these problems. Global constants are good practice. Global variables are the ones to avoid.
Worked Example
Static Local Counts Across Calls
An ordinary local variable is created when control reaches its declaration, and destroyed at the closing brace of its block. So every call gets a brand-new one. That's why the obvious way to count calls doesn't work. Here, plain is created fresh on every call. Kept is declared static, so it's created once, on the first call only. On every call, plain goes from 0 to 1. Kept goes from 0 to 1, then 1 to 2, then 2 to 3. So the output is 1 1, then 1 2, then 1 3. Only the second column counts anything. A static local is initialized the first time control passes through its declaration, and never again. Its reach is unchanged: the name is still local to the function. Only its lifetime is different.
Caution
Use Static Locals Sparingly
Use static locals sparingly, for the same reason as globals. A function with a static local doesn't give the same answer to the same question twice. Its result depends on how many times it's been called before. That's exactly what you want for a call counter, or a cached value. And it's exactly what makes a function hard to test everywhere else. So before reaching for one, ask whether the caller could keep the value instead, and pass it in.
Comparison
Four Kinds of Variables Side by Side
Here are the four kinds side by side. A local variable reaches from its declaration to the end of its block, and is created and destroyed with each pass. With no starting value, it holds whatever was in memory. A function parameter reaches the function body, lasts one call, and is always initialized from the argument. A static local still reaches only its block, but lives from the first call to the end of the program, starting at zero. A global reaches from its declaration to the end of the file, lives for the whole run, and starts at zero. Locals are the only kind where an unstated starting value is dangerous: using an uninitialized local is undefined behavior. That's why initializing at the point of declaration matters most inside functions.
Common Mistakes
Diagnosing Scope and Lifetime Faults
Here are the faults that come from getting this wrong. Use of undeclared identifier, for a name you did declare, usually means it was declared inside a block that has since closed. Declare it in the enclosing block. If an assignment appears to do nothing, a local is usually shadowing the variable you meant to change. A function giving different answers on the same input reads a global, or a static local left over from earlier. And a local holding nonsense on first use was declared without a starting value.
Quick Check
Predict the Static and Global Output
Quick check. A global n holds 5. Bump keeps a static n of its own, starting at zero, and prints it after adding one. Main calls bump twice, then prints n. What appears? Pause and predict. 1 2 5. The static n survives between calls, so bump prints 1, then 2. Inside bump, it hides the global. In main, n is still the global, holding 5.
Key Takeaways
Reach Stays Local, Lifetime Can Persist
To summarize. A name reaches from its declaration to the end of its block. Inner blocks see outward, never inward. Avoid global variables. Global constants are fine. Ordinary locals start fresh on every call. A static local lives on between calls, but its reach stays local.
About C++ Programming at UPI Study
C++ Programming (Computer Science 242) is a self-paced online course of 84 video lessons in 11 chapters, from your first program to decisions, loops, arrays, functions, classes, files, pointers and inheritance. It carries a NCCRS credit recommendation for 3 semester credits.
Every lesson transcript is free on pages like this one, and the videos are free with a free UPI Study account. Enrolling adds a practice quiz after each lesson, the graded work and final exam that earn the credit, lifetime access, and an official transcript on completion. UPI Study has helped over 130,000 students with college credits. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Enroll now → Course details Download the syllabus Every course with PRO →
Why take it here
Why students take C++ Programming with UPI Study
Where the credit goes
Universities that work with NCCRS
C++ Programming carries a NCCRS credit recommendation. These universities work with NCCRS; some are UPI Study's signed partners. ACE and NCCRS have over 2,100 cooperating colleges that will consider accepting credits; the final decision is with the universities.
Thomas Edison State UniversitySigned partner
University of the PeopleSigned partner
Charter Oak State CollegeSigned partner
Strayer UniversitySigned partner
Columbia Southern UniversitySigned partner
Indiana TechSigned partner
Penn StateWorks with NCCRS
Southern New Hampshire UniversityWorks with NCCRS
SUNYWorks with NCCRS
+many more cooperating universitiesFind my college →Find my college → Not listed? Ask Athena in the corner of this page, or book a 15-minute call.
FAQ
Questions students ask us
About Lifetime and Reach
How do I access a global variable when a local variable has the same name in C++?
How do I keep a variable's value between function calls in C++?
Where can a variable declared inside a block, loop, or function parameter be used in C++?
Why does my assignment to a variable seem to do nothing in C++?
About the C++ Programming course
How many college credits is C++ Programming?
How much does C++ Programming cost and what is included?
Which universities accept UPI Study credits?
How long does C++ Programming take?
How are the exams done?
How do my credits reach my college?
Ready for the full course? Earn 3 credits in C++ Programming.
84 video lessons, a quiz after each one, and the graded work that earns the credit. Recommended for credit by NCCRS.
3 credits · NCCRSEnroll →