Variable Scope and Lifetime


Thus far, all variables have been defined at the top of the main function. In programs where the only function is main, those variables can be accessed throughout the entire program since main is the entire program. However, once we start dividing up the code into separate functions, issues arise concerning variable scope and lifetime.

The issue of variable scope was introduced in Chapter 8 in connection with the do while loop. The issue of variable lifetime is new.

Local Variables

You can call the same function multiple times. The following program attempts to call the printMessage function in a loop until the user decides to stop, and each time outputs the number of times the printMessage function has been called. The goal is that the first time the printMessage function is called, the output will be This function called 1 times (pardon the bad grammar), the second time the printMessage function is called, the output will be This function called 2 times and so on.

 #include <iostream> using namespace std; void printMessage(void);  int main () {  int times = 0;  char choice;  do {  cout << "Enter Q to quit, any other character to continue: ";  cin >> choice;  if (choice == 'Q')  cout << "Input stopped";  else  printMessage();   } while (choice != 'Q');  return 0; } void printMessage (void) {   times++;  cout << "This function called " << times << " times\n"; } 

This code will not compile. The reference to the string variable times in the printMessage function will be highlighted, the error message being that this variable is an undeclared identifier.

The reason for the compiler error is that the scope of the variable times is limited to the main function in which it was declared. The issue of variable scope was discussed in Chapter 8 in connection with the do while loop. You cannot refer to a variable outside the scope in which it was declared. A variables scope is within the curly braces in which it was declared. Therefore, the scope of the variable times is limited to the main function. Stated another way, the variable times is a local variable, in this case local to the main function. An attempt to access a local variable outside of the function in which it was declared results in a compiler error.

This compiler error can be fixed by moving the declaration of times into the printMessage function as in the following program:

 #include <iostream> using namespace std; void printMessage(void);  int main () {  char choice;  do {  cout << "Enter Q to quit, any other character to continue: ";  cin >> choice;  if (choice == 'Q')  cout << "Input stopped";  else  printMessage();   } while (choice != 'Q');  return 0; } void printMessage (void) {  int times = 0;  times++;  cout << "This function called " << times << " times\n"; } 

Here is some sample input and output:

 Enter Q to quit, any other character to continue: X This function called 1 times Enter Q to quit, any other character to continue: Y This function called 1 times  Enter Q to quit, any other character to continue: Z This function called 1 times Enter Q to quit, any other character to continue: Q Input stopped 

While this program compiles, the output is not exactly what we wanted. The variable times in the printMessage function does not remember the previous times that function was called.

Variables, like people, have a lifetime. A persons lifetime begins at birth. A variables lifetime begins when it is declared. A persons lifetime ends with death. A variables lifetime ends when it goes out of scope.

The variable times is local to the printMessage function since it was declared in that function. Being a local variable, each time the printMessage function is called, the variable times is created, and each time the printMessage function ends, the variable times is destroyed . Accordingly, the variable times the second time the printMessage function is called is not a continuation of the variable times that was created the first time the printMessage function was called. Rather, the variable times starts all over again each time the printMessage function is called.

There are two alternative methods to having the value of a variable persist between function calls. One is to make the variable global rather than local. The other is to keep the variable local but make it static. These alternatives are covered next .

Global Variables

A variable may be global instead of local. The term global means that the variable has scope throughout the program. Since the variable has scope throughout the program, its lifetime does not end until the program ends.

To make a variable global, it must be declared above all function definitions, generally with function prototypes . The following program makes only one change from the previous one. The declaration of the variable times is moved from inside main to above main, making times a global variable.

 #include <iostream> using namespace std; void printMessage(void); int times;  int main () {  times = 0;   char choice;  do {  cout << "Enter Q to quit, any other character to continue: ";  cin >> choice;  if (choice == 'Q')  cout << "Input stopped";  else  printMessage();   } while (choice != 'Q');  return 0; } void printMessage (void) {  times++;  cout << "This function called " << times << " times\n"; } 

Here is some sample input and output:

 Enter Q to quit, any other character to continue: X This function called 1 times Enter Q to quit, any other character to continue: Y This function called 2 times  Enter Q to quit, any other character to continue: Z This function called 3 times Enter Q to quit, any other character to continue: Q Input stopped 

This is the output we wanted!

Perhaps because of the ease of using global variables to solve the issue of the scope and lifetime of the times variable, beginning programmers often make all variables global so they can access these variables anywhere and anytime in their program. This is not a good idea.

While the good news is that a global variable can be accessed throughout your program, this also is the bad news. The fact that a global variable can be accessed and changed anywhere in your program makes it more difficult to determine why, for example, a global variable has an invalid value than if the variables scope was far more limited. This is simply because the more limited a variables scope, the less places there are in the code that might affect its value.

Therefore, global variables can make it more difficult to fix problems with your programs. For this reason, some programmers, and programming teachers , go to the extreme and pronounce that all global variables are evil. Im not sure I would go that far, but I would recommend that you not use global variables unless you have a very good reason to do so, since there usually are better alternatives. One alternative, a static local variable, is examined next.

Static Local Variables

Up until now a variables lifetime was dictated by its scope. Since a local variables scope was limited to the function in which it was declared, the local variables lifetime ended when that function ended. Since a global variable had scope throughout a program, the global variables lifetime did not end until the entire program ended.

A static local variable is different. A static local variable has the scope of a local variable but the lifetime of a global variable. This may seem counter-intuitive, so to illustrate lets modify the printMessage function we have been working with.

A static local variable is declared exactly like a local variable, within a function rather than above all functions as with a global variable. The difference between the declaration of a static local variable and a nonstatic, or automatic, local variable is that a static local variable is declared with the static keyword, and usually also with a starting value. Thus, in the following program, instead of the declaration

 int times; 

the declaration is

 static int times = 0; 

Here is the program in its entirety:

 #include <iostream> using namespace std; void printMessage(void);  int main () {  char choice;  do {  cout << "Enter Q to quit, any other character to continue: ";  cin >> choice;  if (choice == 'Q')  cout << "Input stopped";  else  printMessage();   } while (choice != 'Q');  return 0; } void printMessage (void) {  static int times = 0;  times++;  cout << "This function called " << times << " times\n"; } 

Here is some sample input and output:

 Enter Q to quit, any other character to continue: X This function called 1 times Enter Q to quit, any other character to continue: Y This function called 2 times  Enter Q to quit, any other character to continue: Z This function called 3 times Enter Q to quit, any other character to continue: Q Input stopped 

This output also is correct. Lets now analyze how the program works.

The first time the printMessage function is called, the variable times is declared, and initialized to zero, by the statement:

 static int times = 0; 

The variable times then is incremented and outputted, resulting in the output:

 This function called 1 times 

So far, this is the same as when times was an automatic local variable rather than a static local variable. The difference is that when the printMessage function ends, times, being a static local variable, is not destroyed. That variable and its value remain in memory.

The next (second) time the printMessage function is called, the statement declaring and initializing variable times is not executed because that variable, being static, still exists from the first time the printMessage function was called. Further, the value of the times variable at the end of the first call of the printMessage function, 1, remains in memory. That value then is incremented to 2, and outputted, so the output to the second call of the printMessage function is

 This function called 2 times 

Accordingly, we were able to persist the value of the times variable between function calls by making that variable either global or static local. The difference was that as a static local variable the scope of times still was limited to the printMessage function, as opposed to having scope throughout the program if it were a global variable. This more limited scope would make it easier to fix your program if the value of the times variable were incorrect somewhere in your code.




C++ Demystified(c) A Self-Teaching Guide
C++ Demystified(c) A Self-Teaching Guide
ISBN: 72253703
EAN: N/A
Year: 2006
Pages: 148

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net