C++ PROGRAMMING ยท 15 MIN STUDY

Scope, lifetime, and storage duration

Learn where names are visible, how long objects live, and why dangling references occur.

Learning objectives

  • Distinguish scope from lifetime.
  • Recognize block scope and local variables.
  • Explain automatic and static storage duration at an introductory level.
  • Identify a dangling pointer or reference.

Prerequisites: understand variables, functions, blocks, and references. Review Functions and References before studying object lifetime.

Scope and lifetime answer different questions

Scope is where a name can be used in source code. Lifetime is the period during program execution when an object exists. A name can stop being visible at the end of a block, and an object with automatic storage duration is normally destroyed there too, but these are separate language concepts.

Block scope

C++17
#include <iostream>

int main() {
    int outer{10};
    if (outer > 0) {
        int inner{5};
        std::cout << outer + inner << '\n';
    }
    // inner is not in scope here
    std::cout << outer << '\n';
}

inner is declared inside the if block. Its name cannot be used after the closing brace. outer is declared in the function block and is visible inside the nested block.

Automatic storage duration

Most ordinary local variables have automatic storage duration. Their lifetime begins when execution reaches their initialization and ends when their block is exited. This is why returning a pointer or reference to such a local object is unsafe.

Static storage duration

Objects with static storage duration exist for the duration of the program. A namespace-scope variable has static storage duration. A local variable declared with static also has static storage duration and retains its value between function calls.

C++17
#include <iostream>

void count_calls() {
    static int calls{0};
    ++calls;
    std::cout << calls << '\n';
}

int main() {
    count_calls(); // 1
    count_calls(); // 2
}

The local name calls has block scope, so it is only usable inside the function. Its object has static storage duration, so it persists between calls. This example shows clearly that scope and lifetime are not the same thing.

Dangling references

A pointer or reference is dangling when the object it refers to has ended its lifetime. Accessing the object through that dangling handle is not valid.

int* make_bad_pointer() {
    int local{7};
    return &local; // WRONG: local dies when function returns
}

Return an object by value when the caller needs a result. If dynamic lifetime is genuinely required, use an owning standard-library type such as std::vector or std::unique_ptr rather than inventing manual ownership.

Common mistakes

  • Thinking scope and lifetime mean the same thing.
  • Using a local variable after its block has ended.
  • Returning the address of a local object.
  • Using static to preserve state without considering that repeated calls now share that state.

Practice

  1. Draw nested blocks and mark where each variable name is visible.
  2. Predict the output of the count_calls program.
  3. Explain why calls has block scope but static storage duration.
  4. Repair the bad pointer function by returning an int value instead.

Practice solutions

Show worked solutions
  1. Draw one outer box for the function block and a smaller nested box for the inner block. Names declared in the outer block are visible in the inner block; names declared only in the inner block stop being visible at its closing brace.
  2. The output is 1 and then 2, each on its own line, because the static local variable retains its value between calls.
  3. The declaration is inside the function block, so the name is visible only there. The static storage duration means the object exists for the entire program and is not recreated on each call.
  4. Return the value rather than its address:
    int make_value() {
        int local{7};
        return local;
    }
    The returned int is a value independent of the local object's expired lifetime.

Check your understanding

Can an object outlive the scope of its local name?

Answer: Yes. A local static object has block scope but static storage duration, so it continues to exist after the function call ends.

Summary

Scope controls where a name is visible. Lifetime controls how long the object exists. Understanding both prevents invalid access and helps you choose safe interfaces.

References