C++ Global and Local Scope

Learn more about how and when we can access variables, by understanding the importance of the scope in which they exist.
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

3D art of a man using a telescope
Ryan McCombe
Ryan McCombe
Posted

We have thus far been declaring our variables outside of any function body. Variables declared in this way are considered global variables.

We can access these variables anywhere within the same file.

// A global variable
int x { 5 };

void Increment() {
  x++;  // We have access to x here
}

int copyOfX { x }; // And here

int main() {
  cout << x;  // And here
}

This is often not a good thing - when we have lots of variables, having them accessible and modifiable from anywhere can become very messy. Additionally, when our software spans multiple files, which it will do later, there are further complications to worry about.

We will soon see many different ways to organize our data in preparation for more complex programs, but for now, let's introduce the local scope.

Local Scope in C++

Names that are declared within the body of a function have local scope. These variables are only available to that function.

We have already seen an example of local scope with our function parameters. Parameters have local scope:

int Increment(int x) {
  return x + 1;
}

// x is not defined in this scope
int CopyOfX { x };

We can also declare additional variables within the body of a function. Those variables will also have local scope, and only be available within that function.

int Health { 100 };
bool isDead { true };

void TakeDamage(int Damage) {
  int DamageToInflict = isDead ? 0 : Damage;
  Health -= DamageToInflict;
}

// Neither of these variables are defined in this scope
int MyVariable { Damage };
int AnotherVariable { DamageToInflict };

We can note that from the global scope, we cannot access variables inside the function scope. However, from the function scope, we can access variables in the global scope.

This is an important concept. We can think of scopes as being nested inside of each other. The function scope is nested within the global scope where the function is defined.

These relationships are often described in terms of a family tree - a function's scope might be a "child" of the global scope; that global scope would be the "parent" of the function's scope.

With this relationship, a child has access to its parent scope, but a parent does not have access to the scope of any of its children.

If a line of code is accessing a variable that does not exist in the same scope as that line of code, the compiler will then check the parent scope.

If it's not defined there either, it will check the parent of that scope. It will keep moving up the tree until it either finds the variable, or reaches the top at which point it will throw an error.

Test your Knowledge

What is the value of Result after running this code?

int x { 1 };
int Add(int y) {
  return x + y;
}
int Result { Add(2) };

Variable Shadowing

Because of this nesting, it is possible to have multiple variables of the same name, accessible within the same scope:

int x { 1 };

int GetNumber() {
  int x { 2 };
  return x;
}

In this scenario, both the x from the local scope and the x from the parent scope are accessible in our GetNumber function.

This code will work, and the function returns 2, because the narrowest available scope is used before the compiler checks outer scopes.

However, where possible, this variable shadowing (sometimes called name masking) is something to avoid, as it can make our code a bit more difficult to understand for humans.

Test your Knowledge

What is the value of Result after running this code?

1int x { 1 };
2int Add(int y) {
3  int x { 2 };
4  return x + y;
5}
6int Result { Add(x) };
7

What value will GetNumber return?

1int x { 1 };
2
3int GetNumber() {
4  x = 2;
5  int x { 3 };
6  return x;
7}
8

What will be the value of Result after running the following code? Only the highlighted line has changed from the previous question.

1int x { 1 };
2
3int GetNumber() {
4  x = 2;
5  int x { 3 };
6  return x;
7}
8
9int Result { x + GetNumber() };
10

What will be the value of Result after running the following code? Only the highlighted line has changed from the previous question.

1int x { 1 };
2
3int GetNumber() {
4  x = 2;
5  int x { 3 };
6  return x;
7}
8
9int Result { GetNumber() + x };
10

Block Scope in C++

We have been creating block scopes (sometimes called statement scopes) when we use things like if statements. These blocks, enclosed by { and } have their own scope, where we can also define variables.

1int CalculateDamage(int Damage) {
2  if (isEnraged) {
3    int DamageToInflict = Damage * 2;
4  } else {
5    int DamageToInflict = Damage;
6  }
7
8  // DamageToInflict is not defined in this scope
9  return DamageToInflict;
10}
11

This above example will result in an error - but not for the reason many might assume. We are creating two variables with the same name, but this is not an issue, because the two variables are being created in different scopes.

We have a variable inside the scope of the if block, and another inside the scope of the else block. The issue comes when we try to access either of these variables on line 9.

The variables are in the scopes created by the if and else blocks. These blocks are children of the function, but the function scope does not have access to its children. Therefore, line 9 is not valid.

Like with earlier examples, we can access and modify variables in parent scopes. Therefore, we can approach this problem by defining the variable in the function scope, and then modifying it within the child scopes created by the if and else blocks.

With those changes, our code would work correctly:

int CalculateDamage(int Damage) {
  int DamageToInflict;
  if (isEnraged) {
    DamageToInflict = Damage * 2;
  } else {
    DamageToInflict = Damage;
  }

  return DamageToInflict;
}

The above code does let us demonstrate some properties of scopes, but it's always reflecting on our entire approach. Is there a simpler way to write this function?

Remembering earlier topics on using early return statements, we could simplify things to this:

int CalculateDamage(int Damage) {
  if (isEnraged) {
    return Damage * 2;
  }
  return Damage;
}

Or, we could use a ternary statement to create the same logic in a single line of code:

int CalculateDamage(int Damage) {
  return isEnraged ? Damage * 2 : Damage;
}

Test your Knowledge

What is the value of Result after running this code?

int Maths(int x, int y, bool subtract) {
  if (subtract) {
    int SubtractResult = x - y;
  } else {
    int AdditionResult = x + y;
  }
  return subtract ? SubtractResult : AdditionResult;
}
int Result { Maths(1, 2, false) };

Compound Statements

We've seen a few scenarios now where we add { and } to our code.

The most common case has been if statements. We add { and } to do multiple things when our if statement is true.

There are many names for these - "compound statements", "block statements" or simply "blocks".

We can introduce these blocks independant of any other code. They don't need to be attached to if statements or anything else.

The main effect of this is that it creates a new scope.

int main() {
  string Message { "Parent Scope" };
  cout << Message;
  {
    string Message { "Child Scope" };
    cout << Message;
  }
  cout << Message;
}

This program will log out "Parent Scope", "Child Scope", and then "Parent Scope" again.

Adding arbitrary blocks like this is a rather niche thing to do, but hopefully this example did help solidify our knowledge of child and parent scopes.

Up next, we're going to introduce forward declarations, which will allow us to work around the restriction that all our functions have to be defined before we can use them.

Was this lesson useful?

Ryan McCombe
Ryan McCombe
Posted
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

3D art showing a progammer setting up a development environment
This lesson is part of the course:

Intro to C++ Programming

Become a software engineer with C++. Starting from the basics, we guide you step by step along the way

Free, unlimited access!

This course includes:

  • 66 Lessons
  • Over 200 Quiz Questions
  • Capstone Project
  • Regularly Updated
  • Help and FAQ
Next Lesson

Forward Declarations in C++

Understand what function prototypes are, and learn how we can use them to let us order our code any way we want.
3D art showing a technician character
Contact|Privacy Policy|Terms of Use
Copyright © 2023 - All Rights Reserved