A name in C++ has three main properties, Duration, Scope, and Linkage.
Not all names have all three properties. For example, a function does not have the Duration property. While Duration determines how long a name remains in memory before it is destroyed, Scope and Linkage deal with the visibility and access of these names. Scope works within a translation unit whereas Linkage works between translation units.
Duration can be one of automatic, static, thread or dynamic.
Automatic storage duration: A variable with automatic storage duration is allocated at the beginning of the block( ‘{‘) and destroyed at the end (‘}’).
Static storage duration: A variable with static storage duration is allocated at the beginning of the program and remains in memory until the end of the program execution.
Thread storage duration: A variable with thread storage duration is allocated at the beginning of the thread and destroyed when the thread is destroyed.
Dynamic storage duration: A variable with dynamic storage duration remains in memory until it is explicitly destroyed.
Scopes are areas within which names can be accessed. Although, there are around five types of “official” scopes in C++, following are the most important at least according to me.
Local Scope (Block Scope) – A variable declared within a block is only accessible within the block. A block can be considered as the area within two curly braces (“{” and “}”). Some of these variables might exist in memory until the end of the program (static variable, for example) but they will never be accessible outside of the block where they are declared. Please note that the scope starts from the line where the variable is declared up to the closing brace (“}”).
Global Scope/ Global Namespace Scope / File Scope – A variable declared outside of a block falls under this category. These types of variables are accessible throughout the file where they are declared. The scope of a global variable actually extends to the entire translation unit. As we discussed before, a translation unit is nothing but a larger source file after the pre-processor has added the included files into the original file. Note that even global variables are not directly accessible to other translation units that might be part of the same project.
It is when you want to access a global variable declared in one translation unit in another translation unit that you use the Linkage property of these variables. A non-constant global variable has external linkage by default. It means that you will be able to use this variable in other translation units just by providing a forward declaration. If you want to make this variable unavailable in other translation units, it can be declared as a static variable. A static global variable will not be visible in other translation units. A constant global variable has internal linkage by default. This means that it will not be available in other translation units. You can add the keyword ‘extern’ to the front of this variable to give it an external linkage and make it available in other translation units. To summarize,
int var1; // has external linkage by default.
static int var2; // explicit change to internal linkage.
const int var3; // internal linkage by default.
extern const int var4; // explicit change to external linkage
Please note that if you need to access a variable (with external linkage) declared in the file ‘a.cpp‘ in another file ‘b.cpp‘, you will need to provide a forward declaration of the variable in ‘b.cpp‘. The scope of this variable in ‘b.cpp‘ depends on where you specify the forward declaration within the file. A forward declaration looks like the following
extern int var1;
The same keyword ‘extern’ is used for forward declaration as well as to explicitly provide external linkage to const variables. Be sure to understand the two use-cases.