Cpp Chapter 9: Memory Models and Namespaces Part1

9.1 Separate compilation

) C++ could compile multiple files separately and link them into the final executable program

) You can divide original program into three parts(three files):

  1. A header file that contains structure declarations and prototypes for functions that use those structures

  2. A source code file that contains the code for structure-related functions

  3. A source code file that contains the code for calling those functions

) Common things in header files: function prototypes, symbolic constants, structure declarations, class declarations, template declarations, inline functions

) Use #include "coordin.h" instead of #include <cooridn.h> while using user-defined header files. If a file name is enclosed in <>, C++ will look for the place for those standard header files. If a file is enclosed in "", C++ will first look for it at the current workspace, then the standard location

) In order to prevent multiple inclusion of a single header file, C++ develops this mechanism:

1 #ifndef COORDIN_H_
2 #define COORDIN_H_
3 // place header file content
4 #endif

Line 1 detects whether file "coordin.h" is already included or not, if so, it the content between #ifndef and #endif will be compiled. Line 2 marks the inclusion of file "coordin.h", so next time trying to include coordin.h will be ignored.

Here's an example of three separate files tring to convert rectangle to polar coordinates:

 1 // coordin.h -- structure templates and function prototypes
 2 #ifndef COORDIN_H_INCLUDED
 3 #define COORDIN_H_INCLUDED
 4 
 5 struct polar
 6 {
 7     double distance;
 8     double angle;
 9 };
10 
11 struct rect
12 {
13     double x;
14     double y;
15 };
16 
17 polar rect_to_polar(rect xypos);
18 void show_polar(polar dapos);
19 
20 #endif // COORDIN_H_INCLUDED
 1 // file1.cpp -- example of a three-file program
 2 #include <iostream>
 3 #include "coordin.h"
 4 using namespace std;
 5 int main()
 6 {
 7     rect rplace;
 8     polar pplace;
 9     cout << "Enter the x and y values ";
10     while (cin >> rplace.x >> rplace.y)
11     {
12         pplace = rect_to_polar(rplace);
13         show_polar(pplace);
14         cout << "Next two numbers (q to quit): ";
15     }
16     cout << "Bye!\n";
17     return 0;
18 }
 1 // file2.cpp -- contains function called in file1.cpp
 2 #include <iostream>
 3 #include <cmath>
 4 #include "coordin.h" // structure templates and function prototypes
 5 
 6 polar rect_to_polar(rect xypos)
 7 {
 8     using namespace std;
 9     polar answer;
10 
11     answer.distance = sqrt(xypos.x * xypos.x + xypos.y * xypos.y);
12     answer.angle = atan2(xypos.y, xypos.x);
13     return answer;
14 }
15 
16 void show_polar(polar dapos)
17 {
18     using namespace std;
19     const double Rad_to_deg = 57.29577951;
20     cout << "distance = " << dapos.distance << ", angle = " << dapos.angle * Rad_to_deg <<" degrees\n";
21 }

As illustrated previously, coordin.h contains structure declarations and function prototypes. file1.cpp contains code using those functions. file2.cpp contains code defining those functions.

) C++ standard uses the word "translation unit" for file.

) In Code::Blocks, you create a project and add header files and source code files to the project, thus you could compile multiple files together and generate executable program.

9.2 Storage Duration, Scope, and Linkage

) Review: three schemes for storing data:

  1. Automatic storage duration: variables defined within a function or a block, which are created when the program enters the block and freed when the program goes out.

  2. Static storage duration: variables defined outside a function or with keyword static. They persist for the entire time a program is running.

  3. Dynamic storage duration: memory allocated by new operator and deleted by delete operator. Sometimes termed free store or heap.

9.2.1 Scope and Linkage

) Scope: how widely visible a name is in a file

  1. local scope: known only within the block it is defined

  2. global scope: known throughout the file after the point it is defined

  3. function prototype scope, class scope, namespac scope

) Linkage: how a name can be shared in different translation units

  1. external linkage: can be shared across files

  2. internal linkage: can be shared by functions within a single file

  Note: automatic variables have no linkage

9.2.2 Automatic Storage Duration

) Functions parameters and variables declared in a function have automatic storage duration, local scope and no linkage by default. 

) If you define a variable inside a block, the variable's persistence and scope are confined to that block.

) If you have two same-name variables with one in outer block and one in inner block, the new definition hides the prior definition, meaning that the old definition is temporarily out of scope.

Here is an example of sharing-name variables:

 1 // autoscp.cpp -- illustrating scope of automatic variables
 2 #include <iostream>
 3 void oil(int x);
 4 int main()
 5 {
 6     using namespace std;
 7     int texas = 31;
 8     int year = 2011;
 9     cout << "In main(), texas = " << texas << ", &texas = " << &texas << endl;
10     cout << "In main(), year = " << year << ", &year = " << &year << endl;
11     oil(texas);
12     cout << "In main(), texas = " << texas << ", &texas = " << &texas << endl;
13     cout << "In main(), year = " << year << ", &year = " << &year << endl;
14     return 0;
15 }
16 
17 void oil(int x)
18 {
19     using namespace std;
20     int texas = 5;
21     cout << "In oil(), texas = " << texas << ", &texas = " << &texas << endl;
22     cout << "In oil(), x = " << x << ", &x = " << &x << endl;
23     {
24         int texas = 113;
25         cout << "In block, texas = " << texas << ", &texas = " << &texas << endl;
26         cout << "In block, x = " << x << ", &x = " << &x << endl;
27     }
28     cout << "Post-block texas = " << texas << ", &texas = " << &texas << endl;
29 }

) The program uses a stack to store automatic variables by keeping track with two pointers, one to the base and one to the top(next insertion location). A stack is a LIFO design, meaning that the last variable added to the stack is the first to go.

9.2.3 Static Duration Variables

) To store static duration variables, the compiler allocates a fixed block of memory to hold the static variables, instead of using a special device such as a stack.

) If you don't explicitly initialize a static variable, the compiler sets it to 0.

) The five kinds of variable storage:

Storage Description Duration Scope Linkage How Declared
Automatic Automatic Block None In a block
Register Automatic Block None In a block with the keyword register
Static with no linkage Static Block None In a block with keyword static
Static with internal linkage Static File Internal Outside all functions
Static with external linkage Static File External Outside all functions with the keyword static

Duration: (automatic/static) the time that the variable exists before being freed. Automatic means freed outside the block, static means exist all through the program execution.

Scope: (block/file) the range that the variable could be accessed. Block means only accessed within the block it is declared, file means accessable throughout the file.

Linkage: (none/internal/external) the availability of variable in different files or units. None means only accessed within block, internal means accessed within file, external means accessible across files.

Here's an example illustrating these storage patterns:

int global = 100; // static duration, external linkage
static int one_file = 50; // static duration, internal linkage
void funct1(int n)
{
    static int count = 0; // static duration, none linkage
    int llama = 0; // automatic duration, none linkage
}

) Initializing Static variables:

  1. zero-initialized: if you don't initialize the variable when declare it

  2. constant expression initialization: initialize variable with a constant expression that the program could evaluate solely from the file contents(calculations allowed)

  3. dynamic initialization: no enough information at the initializing time

Here's an example illustrating these initial patterns:

int x; // zero-initialization
int y = 5; // constant-expression initialization
int z = 13 * 13; // constant-expression initialization
const double pi = 4.0 * atan(1.0); // dynamic initialization

 

posted @ 2018-09-29 22:18  Gabriel_Ham  阅读(146)  评论(0编辑  收藏  举报