Home arrow C++ arrow Page 11 - More on Handling Basic Data Types
C++

More on Handling Basic Data Types


Have you ever wanted to learn how basic types of C++ variables interact in complex situations? Ivor Horton explains this, and also describes some interesting features of C++. This article is from chapter 3 of Ivor Horton's Beginning ANSC C++ The Complete Language (Apress, 2004; ISBN 1590592271).

Author Info:
By: Apress Publishing
Rating: 4 stars4 stars4 stars4 stars4 stars / 10
March 02, 2005
TABLE OF CONTENTS:
  1. · More on Handling Basic Data Types
  2. · Try It Out: Explicit Casting
  3. · Finding Out About Types
  4. · Try It Out: Finding the Sizes of Data Types
  5. · Using the Bitwise AND
  6. · Using the Bitwise Exclusive OR
  7. · Try It Out: Using the Bitwise Operators
  8. · More on Output Manipulators
  9. · Enumerated Data Types
  10. · Try It Out: Enumerated Data Types
  11. · The Lifetime of a Variable
  12. · Try It Out: The Scope Resolution Operator
  13. · Declaring External Variables

print this article
SEARCH DEVARTICLES

More on Handling Basic Data Types - The Lifetime of a Variable
(Page 11 of 13 )

All variables have a finite lifetime when your program executes. They come into existence from the point at which you declare them and then, at some point, they disappear—at the latest, when your program terminates. How long a particular variable lasts is determined by a property called its storage duration. A variable can have three different kinds of storage duration:

  • Automatic storage duration

  • Static storage duration

  • Dynamic storage duration

The storage duration that a variable has depends on how you create the variable. I defer discussion of variables with dynamic storage duration until Chapter 7, but you’ll look into the characteristics of the other two kinds of storage duration in this chapter.

Another property that variables have is scope. The scope of a variable is simply that part of your program in which the variable name is valid. Within a variable’s scope, you can legally refer to it, set its value, or use it in an expression. Outside of the scope of a variable, you can’t refer to its name—any attempt to do so will cause a compiler error. Note that a variable may still exist outside of its scope, even though you can’t refer to it by name. You’ll see examples of this situation a little later in this discussion.

All the variables that you’ve declared up to now have had automatic storage duration, and are therefore called automatic variables. Let’s take a closer look at these first.

Automatic Variables

The variables that you’ve declared so far have been declared within a block—that is, between a pair of curly braces. These are called automatic variables and are said to have local scope or block scope. An automatic variable is “in scope” from the point at which it is declared until the end of the block containing its declaration.

An automatic variable is “born” when it’s declared and automatically ceases to exist at the end of the block containing the declaration. This will be at the closing brace matching the first opening brace that precedes the declaration of the variable. Every time the block of statements containing a declaration for an automatic variable is executed, the variable is created anew, and if you specified an initial value for the automatic variable, it will be reinitialized each time it’s created.

You can use the auto keyword to specify explicitly that a variable is automatic, but this keyword is rarely used because it’s implied by default. Let’s put together an example of what you’ve learned so far.


Try It Out: Automatic Variables

You can demonstrate the lifetime of automatic variables with the following example:

  // Program 3.6 Demonstrating variable scope
  #include <lostream>
  using std::cout;
  using std::endl;
  int main() {               // Function scope starts here
  int count1 = 10;
  int count3 = 50;
  cout << endl << "Value of outer count1 = " << count1;
  {                // New block scope starts here...
  int count1 = 20; // This hides the outer count1
  int count2 = 30;
  cout << endl << "Value of inner count1 = " << count1;
  count1 += 3;     // This changes the inner count1
  count3 += count2;
 }                // ...and ends here.
  cout << endl
       << "Value of outer count1 = " << count1
       << endl
       << "Value of outer count3 = " << count3;
  // cout << endl << count2; // Uncomment to get an error
  cout << endl;
  return 0;
}                              // Function scope ends here

The output from this example is as follows:

===========================================

Value of outer count1 = 10
Value of inner count1 = 20
Value of outer count1 = 10
Value of outer count3 = 80

===========================================

HOW IT WORKS

The first two statements declare and define two integer variables, count1 and count3, with initial values of 10 and 50, respectively:

 int count1 = 10;
 int count3 = 50;

Both of these variables exist from this point in the code to the closing brace at the end of the program. The scope of these variables also extends to the closing brace at the end of main().


NOTE Remember that the lifetime and scope of a variable are two different things. Lifetime is the period of execution time over which a variable survives. Scope is the region of program code over which the variable name can be used. It’s important not to get these two ideas confused.

Following the variable definitions, the value of count1 is presented in the first line of output by this statement:

 cout << endl << "Value of outer count1 = " << count1;

There’s then a second opening brace that starts a new block. Two variables, count1 and count2, are defined within this block, with the values 20 and 30, respectively. The count1 variable declared here is different from the first count1. Although the first count1 still exists, its name is masked by the second count1. Any use of the name count1 following the declaration within the inner block refers to the count1 declared within that block.

I’ve duplicated names in this way only to illustrate what happens—it’s not a good approach to programming in general. Doing this kind of thing in a real program would be confusing and unnecessary, and produce code that was extremely prone to error.

The output statement shows by the value in the second line that you’re using the count1 in the inner scope—that is, inside the innermost braces:

{                       // New block scope starts here...
 int count1 = 20;       // This hides the outer count1
 int count2 = 30;
 
cout << endl << "Value of inner count1 = " << count1;

Had you still been using the outer count1, this statement would have output the value 10. The variable count1 is then incremented by this statement:

  count1 += 3;          // This changes the inner count1

The increment applies to the variable in the inner scope, because the outer one is still hidden. However, count3, which was defined in the outer scope, is incremented without any problem by the next statement:

  count3 += count2;

This shows that the variables that were defined at the beginning of the outer scope are still accessible in the inner scope. They could have been defined after the second of the inner pair of braces and still be within the outer scope, but in that case they wouldn’t exist at the point that you’re using them.

After the brace ending the inner scope, count2 and the inner count1 cease to exist. Their lifetime has come to an end. The variables count1 and count3 are still there in the outer scope, and their values are displayed by this statement, demonstrating that count3 was indeed incremented in the inner scope:

 cout << endl
      << "Value of outer count1 = " << count1
      << endl
      << "Value of outer count3 = " << count3;

If you uncomment the next line

// cout << endl << count2;   // uncomment to get an error

the program will no longer compile correctly, because it attempts to output a nonexistent variable.


Positioning Variable Declarations

You have great flexibility in where you place the declarations for your variables. The most important issue to consider is what scope the variables need to have. Beyond that, you should generally place a declaration close to where the variable is first to be used in a program. You should always write your programs with a view to making them as easy as possible for another programmer to understand, and declaring a variable close to its first point of use can be helpful in achieving that.

It’s possible to place variable declarations outside all of the functions that make up a program. Let’s look what effect that has on the variables concerned.

Global Variables

Variables declared outside of all blocks and classes are called globals and have global scope (which is also called global namespace scope). This means that they’re accessible in all the functions in the source file, following the point at which they’re declared. If you declare them at the very top, they’ll be accessible from anywhere in the file.

Globals also have static storage duration by default. Global variables with static storage duration will exist from the start of execution of the program until execution of the program ends. If you don’t specify an initial value for a global variable, it will be initialized with 0 by default. Initialization of global variables takes place before the execution of main() begins, so they’re always ready to be used within any code that’s within the variable’s scope.

Figure 3-4 shows the contents of a source file, Example.cpp, and the arrows indicate the scope of each of the variables.


Figure 3-4.  Variable scope

Figure 3-4 illustrates the extent of the scope of each variable in a file. The variable value1 that appears at the beginning of the file is declared at global scope, as is value4, which appears after the function main(). The global variables have a scope that extends from the point at which they’re declared to the end of the file. Even though value4 exists when execution starts, it can’t be referred to in main() because main() isn’t within the variable’s scope. For main() to use value4, you would need to move its declaration to the beginning of the file. Both value1 and value4 will be initialized with 0 by default, which isn’t the case for the automatic variables. Remember that the local variable called value1 in function() will hide the global variable of the same name.

Because global variables continue to exist for as long as the program is running, this might raise the following question in your mind: “Why not make all variables global and avoid this messing about with local variables that disappear?” This sounds very attractive at first, but there are serious disadvantages that completely outweigh any advantages that you might gain.

Real programs are generally composed of a large number of statements, a significant number of functions, and a great many variables. Declaring all at the global scope greatly magnifies the possibility of accidental, erroneous modification of a variable, and it makes the job of naming them sensibly quite intractable. They’ll also occupy memory for the duration of program execution. By keeping variables local to a function or a block, you can be sure they have almost complete protection from external effects. They’ll only exist and occupy memory from the point at which they’re defined to the end of the enclosing block, and the whole development process becomes much easier to manage.


This article is excerpted from Beginning ANSI C++ The Complete Language by Ivor Horton (Apress, 2004; ISBN  1590592271). Check it out at your favorite bookstore today. Buy this book now.


blog comments powered by Disqus
C++ ARTICLES

- Intel Threading Building Blocks
- Threading Building Blocks with C++
- Video Memory Programming in Text Mode
- More Tricks to Gain Speed in Programming Con...
- Easy and Efficient Programming for Contests
- Preparing For Programming Contests
- Programming Contests: Why Bother?
- Polymorphism in C++
- Overview of Virtual Functions
- Inheritance in C++
- Extending the Basic Streams in C++
- Using Stringstreams in C++
- Custom Stream Manipulation in C++
- General Stream Manipulation in C++
- Serialize Your Class into Streams in C++

Watch our Tech Videos 
Dev Articles Forums 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
Contact Us 
Site Map 
Privacy Policy 
Support 

Developer Shed Affiliates

 




© 2003-2017 by Developer Shed. All rights reserved. DS Cluster - Follow our Sitemap
Popular Web Development Topics
All Web Development Tutorials