Storage Class
Whenever an object is created, space is allocated in one of four possible places. Each of these places is called a storage class.
While scope refers to a region of code where an identifier is accessible, storage class refers to a location in memory.
- The static area: Global variables, static locals, and static data members are all stored in the static storage area. The lifetime of a static object begins when its object module loads and ends when the program terminates.
It is used often for pointers, simple types, and string constants, less often for complex objects.
- The program stack (automatic storageauto[5]):Local variables, function parameters, and temporary objects are all stored on the stack. For local (block-scope) variables, the lifetime is determined by the brackets around the code that is executed.
[5] The optional keyword auto is almost never used.
Objects on the stack include function parameters, return values, local or temporary variables. Stack storage is allocated automatically when an object definition is executed. Objects in this storage class are local to a function or a block of statements.[6]
[6] Or to a member of another object that is
- The heap or free storage (dynamic storage): Objects created via new are examples.
The lifetime of a heap object is determined entirely by the use of new and delete.
In general, the allocation and freeing of heap objects should be in carefully encapsulated classes.
- Another storage class, left over from C, is called register. It is a specialized form of automatic storage. This category of storage can be requested by using the keyword, register in the variable declaration. Most C++ compilers ignore this keyword and put such variables on the stack. Using this storage class for an object means that you cannot take its address.
20.3.1. Globals, statics, and QObject
Global objects need to be "global" for two reasons.
- They need a lifetime that is the same as the application.
- They need to be available from many different places in the application.
In C++, we avoid the use of global scope at all costs, in favor of other approaches. We still use global scope identifiers for the following:
- Class names
- Namespace names
- The global pointer qApp, which points to the running QApplication object
By turning a global object into a static class member, or a namespace member, we can avoid increasing the size of the global namespace while keeping the object accessible from other source code modules.
[7] By "interesting" we mean any class with a destructor that has some important cleaning up to do.
20.3.1.1. Globals and const
The scope of const variables is slightly different from the scope of regular globals.
A global object that has been declared const has file scope, by default. It may be exported to other files by declaring it extern at the point where it is initialized.
For example, in one file, we could have this:
const int NN = 10; //must be initialized //declaration and definition - allocates storage extern const int QQ = 7; int main() { NN = 12; // Error! int array[NN]; // OK QQ++; // Error! return 0; }
In another file, we might have
const int NN = 33; // a different constant // declare global constant - storage allocated elsewhere extern const int QQ; // external declaration ...
The second file has a const int NN that is separate and distinct from the const with the same name in the first file. The second file can share the use of the const int QQ because of the extern modifier.
Exercise: Storage Class
In Example 20.6, identify the scope/storage class of each of object's creation/ definition. If there is a name clash, indicate there is an error with the definition. Example 20.6. src/storage/storage.cpp
|
Namespaces
|