Scope, Duration, and Linkage Summary

Scope, duration, and linkage are fundamental but often confusing concepts. This lesson provides a comprehensive reference summarizing everything, including topics we'll cover later.

Scope Summary

An identifier's scope determines where it can be accessed within source code.

  • Block (local) scope: Variables accessible only from their declaration point until the end of their enclosing block (including nested blocks). This includes:

    • Local variables
    • Function parameters
    • User-defined types (enums, classes) declared inside blocks
  • Global scope: Variables and functions accessible from their declaration point until the end of the file. This includes:

    • Global variables
    • Functions
    • User-defined types (enums, classes) declared inside namespaces or at global scope

Duration Summary

A variable's duration determines when it is created and destroyed.

  • Automatic duration: Variables created at their definition point and destroyed when their block exits. This includes:

    • Local variables
    • Function parameters
  • Static duration: Variables created when the program begins and destroyed when it ends. This includes:

    • Global variables
    • Static local variables
  • Dynamic duration: Variables created and destroyed by programmer request. This includes:

    • Dynamically allocated variables

Linkage Summary

An identifier's linkage determines whether declarations of the same identifier in different scopes refer to the same entity (object, function, reference, etc.).

Local variables have no linkage. Each declaration of an identifier with no linkage refers to a unique entity.

  • No linkage: Each declaration refers to a unique entity. This includes:

    • Local variables
    • User-defined type identifiers (enums, classes) declared inside blocks
  • Internal linkage: Declarations of the same identifier within the same translation unit refer to the same object or function. This includes:

    • Static global variables (initialized or uninitialized)
    • Static functions
    • Const global variables
    • Unnamed namespaces and their contents
  • External linkage: Declarations of the same identifier anywhere in the program refer to the same object or function. This includes:

    • Non-static functions
    • Non-const global variables (initialized or uninitialized)
    • Extern const global variables
    • Inline const global variables
    • Namespaces

Identifiers with external linkage generally cause duplicate definition linker errors if compiled into multiple source files (violating the one-definition rule). Exceptions exist for types, templates, and inline functions/variables—we'll cover these in future lessons.

Note that functions have external linkage by default. They can be made internal using static.

Variable Scope, Duration, and Linkage Summary

Variables have all three properties, summarized in this table:

Type Example Scope Duration Linkage Notes
Local variable int playerHealth; Block Automatic None
Static local variable static int s_sessionID; Block Static None
Dynamic local variable int* buffer{ new int{} }; Block Dynamic None
Function parameter void processInput(int keyCode) Block Automatic None
Internal non-const global variable static int g_gameState; Global Static Internal Initialized or uninitialized
External non-const global variable int g_frameCount; Global Static External Initialized or uninitialized
Inline non-const global variable (C++17) inline int g_windowWidth; Global Static External Initialized or uninitialized
Internal constant global variable constexpr int g_maxPlayers{ 4 }; Global Static Internal Must be initialized
External constant global variable extern const int g_serverPort{ 8080 }; Global Static External Must be initialized
Inline constant global variable (C++17) inline constexpr int g_tileSize{ 32 }; Global Static External Must be initialized

Forward Declaration Summary

Forward declarations allow accessing functions or variables from other files. The declared variable's scope follows usual rules (global scope for globals, block scope for locals).

Type Example Notes
Function forward declaration void renderFrame(int fps); Prototype only, no function body
Non-constant variable forward declaration extern int g_windowWidth; Must be uninitialized
Const variable forward declaration extern const int g_maxConnections; Must be uninitialized
Constexpr variable forward declaration extern constexpr int g_bufferSize; Not allowed, constexpr cannot be forward declared

A constexpr variable (implicitly const) can be forward declared using a const variable forward declaration. When accessed through the forward declaration, it's considered const (not constexpr).

What is a Storage Class Specifier?

When used in identifier declarations, the static and extern keywords are called storage class specifiers. They set the storage duration and linkage of identifiers.

C++ supports four active storage class specifiers:

Specifier Meaning Note
extern Static (or thread_local) storage duration and external linkage
static Static (or thread_local) storage duration and internal linkage
thread_local Thread storage duration
mutable Object allowed to be modified even if containing class is const
auto Automatic storage duration Deprecated in C++11
register Automatic storage duration and hint to compiler to place in register Deprecated in C++17

The term "storage class specifier" appears primarily in formal documentation.

Summary

Scope: Determines where an identifier can be accessed. Block scope (local) is visible from declaration to end of block. Global scope is visible from declaration to end of file.

Duration: Determines when a variable is created and destroyed. Automatic duration (local variables) exists from definition to block exit. Static duration (globals, static locals) exists from program start to program end. Dynamic duration is controlled by programmer.

Linkage: Determines whether declarations of the same identifier refer to the same entity. No linkage means each declaration is independent. Internal linkage means same identifier in different translation units refers to different entities. External linkage means same identifier across the program refers to the same entity.

Variable summary: Local variables have block scope, automatic duration, and no linkage. Global non-const variables have global scope, static duration, and external linkage (or internal with static). Global const variables have global scope, static duration, and internal linkage (or external with extern).

Forward declarations: Allow accessing identifiers from other files. Function forward declarations don't need extern. Non-const and const variable forward declarations use extern without initializer. Constexpr variables cannot be forward declared.

Storage class specifiers: extern and static keywords are storage class specifiers when used in declarations. They set linkage and storage duration.

This comprehensive reference table summarizes the relationships between scope, duration, and linkage for all variable types in C++, serving as a quick lookup for understanding identifier properties.