Cpp Chapter 9: Memory Models and Namespaces Part2

9.2.4 Static duration, external linkage

) External variables

External variables are defined outside, thus external to any function.It is also termed global variables, which could be accessed in any function that follow‘s the external variable‘s definition in the file.

) one definition rule(odr)

One definition rule: there can be only one definition of a variable.

C++ has two types of variable declarations:

definition declaration, or simply called definition, which allocates memory for the variable.

referencing declaration, or simply called declaration, which does not cause the allocation of memory because it refers to an existing variable.This type of declaration uses the keyword extern and does not provide initialization, otherwise it is not a declaration but a definition, causing the memory to be allocated:

double up; // definition, up set to 0
extern int down; // declaration, down should be defined elsewhere
extern int left = 2; // definition because initialized

If you are using external variable in separate files, remember that only one file could contain the definition, other declarations should go with the keyword extern:

// file01.cpp
extern int cats = 20; // definition
int dogs = 22; // definition
int fleas; // definition
// file02.cpp
extern int cats; // declaration, cats defines in file01
extern int dogs; // declaration, dogs defines in file01
//file98.cpp
extern int cats;
extern int dogs;
extern int fleas; // all declaration, using variables defined in file01

Noteworthy that extern in "extern int cats" in file01 isn‘t necessary, omitting it produces same effect.

) variable overlapping

When you declare a local variable inside a function with a same name of a using global variable, it actually hides the global variable.

C++ provides scope resolution operator :: to cope with this. In functions where global and local variables sharing the same name are used, ::variable accesses the global version.

Noteworthy that altering global variable causes its value to change in all files.

Here‘s an example:

// external.cpp -- external variables
// compile with support.cpp
#include <iostream>
using namespace std;
double warming = 0.3; // external variable definition
void update(double dt);
void local();

int main()
{
    cout << "Global warming is " << warming << " degrees.\n";
    update(0.1);
    cout << "Global warming is " << warming << " degrees.\n";
    local();
    cout << "Global warming is " << warming << " degrees.\n";
    return 0;
}
// support.cpp -- use external variable
// compile with external.cpp
#include <iostream>
extern double warming; // external variable declartaion here: defined in external.cpp
void update(double dt);
void local();

using std::cout;
void update(double dt)
{
    extern double warming; // optional redeclaration
    warming += dt; // use global
    cout << "Updating global warming to " << warming;
    cout << " degrees.\n";
}

void local()
{
    double warming = 0.8; // use local varaible
    cout << "Local warming = " << warming << " degrees.\n";
    cout << "But global warming = " << ::warming << " degrees.\n"; // using :: scope resolution operator to access global
}

In support.cpp, the update() changes global variable value. The warming and ::warming in local() uses local(0.8) and global(0.4) variables respectively.


9.2.5 Static duration, internal linkage

Applying the static modifier to a file-scope variable gives an internal linkage:

static int thing; // internal linkage

) variable overlapping:

Rules if you use internal and external variables with same names:

// file1
int errors = 20; // external definition
// file2
static int errors = 10; // internal definition, don‘t contradict with file1
static double thing = 6.5; // internal definition
cout << errors; // the answer should be 10
// file3
double thing = 6.7; // external definition, don‘t contradict with file2
cout << thing; // the answer should be 6.7

You can use static variable with internal linkage to share values between functions within the same file.

Here comes example:

// twofile1.cpp -- variables with external and internal linkage
// to be compiled with twofile2.cpp
#include <iostream>
int tom = 3; // external definition
int dick = 30; // external definition
static int harry = 300; // internal definition

void remote_access();

int main()
{
    using namespace std;
    cout << "main() reports the following addresses:\n";
    cout << &tom << " = &tom, " << &dick << " = &dick, " << &harry << " = &harry\n";
    remote_access();
    return 0;
}
// twofile2.cpp -- variables with internal and external linkage
#include <iostream>
extern int tom; // external declaration; tom defined in twofile1.cpp
static int dick = 10; // internal definition; overrides external dick in twofile1.cpp
int harry; // external definition; no conflict with twofile1.cpp‘s internal harry

void remote_access()
{
    using namespace std;
    cout << "remote_access() reports the following addresses:\n";
    cout << &tom << " = &tom, " << &dick << " = &dick, " << &harry << " = &harry\n";
}

The address of tom is same in both files because tom is external linkage and re-declared in file2, but dick and harry have different addresses in both files, due to the fact that dick is external defined in file1 but internal re-defined in file2, harry is internal defined in file1, but external re-defined in file2. This example illustrates that variables with external linkage and internal linkage with the same name don‘t conflict with each other.


9.2.6 Static storage duration, no linkage

When you use it within a block, static causes a local variable to have static storage duration, which means that though the variable is only known within that block, it exists while the block is inactive.

The program only initialize a static local variable once, subsequent calls to the function don‘t reinitialize it.

Example comes:

// static.cpp -- using a static local variable
#include <iostream>
const int ArSize = 10;
void strcount(const char * str);

int main()
{
    using namespace std;
    char input[ArSize];
    char next;
    cout << "Enter a line:\n";
    cin.get(input, ArSize);
    while (cin)
    {
        cin.get(next);
        while (next != ‘\n‘)
            cin.get(next);
        strcount(input);
        cout << "Enter next line(empty line to quit):\n";
        cin.get(input, ArSize);
    }
    cout << "Bye\n";
    return 0;
}

void strcount(const char * str)
{
    using namespace std;
    static int total = 0; // static local variable
    int count = 0;
    cout << "\"" << str << "\" contains ";
    while (*str++)
        count++;
    total += count;
    cout << count << " characters\n" << total << " characters total\n";
}

In the example of string-length calculation, the total in strcount() is declared to be static, which means that every time calling the strcount() won‘t cause total to be reinitialized, so total acts as a acumulating variable here.


9.2.7 Specifiers and qualifiers

) storage class specifiers

List of storage class specifiers:

specifier|feature

---|---:

auto|prior to C++11, auto indicates that a variable is a automatic variable

register|indicate register storage class, in C++11 simply indicate automatic variable

static|used with file-scope declaration indicates internal linkage, used with local declaration indicates static storage duration

extern|indicates a reference declaration, that is, the declaration refers to a variable defined elsewhere

thread_local|the duration of the variable is the duration of the containing thread

mutable|explained in terms of const

)Cv-qualifiers

const: It indicates that after initialization, the memory should not be altered by a program

volatile: indicates that the value in a memory location can be altered even if no code modifies it. The intent of this keyword is to improve the optimization process of the compiler. When you use a variable for a number of times, the compiler will take it for granted that the value would not change between the places of access if no code explicitly alter the content. Under this circumstance, the compiler will cache the value in a register so later access would be quicker. But in real conditions, such as calling the system time, no code modifies system time but it actually changes between different accesses. So you could declare a variable as volatile, thus the compiler would not make this sort of optimization.

)mutable

You use mutable to indicate that a particular member of a structure or class can be altered even if the structure is const. Example:

struct data
{
    char name[30];
    mutable int accesses;
    ...
};
const data veep = {"fsb", 0, ...};
strcpy(veep.name, "Joye Joux"); // not allowed because veep.name is in a const structure
veep.accesses++; // allowed
>)**more about const**

**A const global variable has internal linkage on default.** Example:

const int fingers = 10; // same as static const int fingers = 10;

This features makes life easier for you to avoid violating the "one definition rule". Thus, to share constant between different files, you had better write it in a header file and include the header file in each file that you use the set of constants.
You could also override the default behavior to make const global variables to have external linkage by using the keyword extern:

extern const int fingers = 10; // definition of const with external linkage


9.2.8 Funtions and linkage

Functions naturally have static storage duration and external linkage.

You could use the keyword static to give a function internal linkage, confining its use to a single file:

static int private(double x)
{
    ...
}

This means that you could use static functions with the same name in different files. As with variables, a static function overrides an external definition for the file containing the static function.

When you declare a function sharing same name with a standard library function, the compiler uses your version rather than the library version.


9.2.9 Language linking

) C language linkage

C doesn‘t allow functions sharing the same name, so a C compiler might translate a function named spiff to **_spiff**

) C++ language linkage

C++ uses name decoration. It may convert spiff(int) to **_spiff_i** and spiff(double, double) to **_spiff_d_d**

When you want to use a function from a C library in a C++ program, to avoid function-linkage matching problems, you could use the function prototype to explicitly tell the compiler which protocol to use:

extern "C" void spiff(int); // use C protocol for name look-up
extern void spoff(int); // use C++ protocol for name look-up
extern "C++" void spaff(int); // use C++ protocol for name look-up


Cpp Chapter 9: Memory Models and Namespaces Part2

原文地址:https://www.cnblogs.com/fsbblogs/p/9745910.html

时间: 2024-10-07 11:35:04

Cpp Chapter 9: Memory Models and Namespaces Part2的相关文章

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 prototyp

Cpp Chapter 12: Classes and Dynamic Memory Allocation Part2

12.3 Things to remember when using new in constructors ) If you use new in constructors, use delete in destructor. Their use should be compatible, pair new with delete and new [] with delete [] ) Multiple constructors should share the same way of new

Cpp Chapter 10: Objects and Classes Part2

10.2.4 Using classes Following exapmle uses the class definition and implementation written in previous files: // usestok0.cpp -- the client program // compiler with stock00.cpp #include <iostream> #include "stock00.h" int main() { Stock s

Cpp Chapter 11: Working with Classes Part2

11.5.3 An implementation comment ) The separation of interface from implementation is one of the goals of OOP. ) Example of the implementation of the class Vector in a rand walk simulation: // randwalk.cpp -- using the Vector class // compile with th

Cpp Chapter 12: Classes and Dynamic Memory Allocation Part1

12.1 Dynamic memory and classes 12.1.1 A review example and static class members Now try implement a String class(a flawed one): // strngbad.h -- flawed string class definition #include <iostream> #ifndef STRNGBAD_H_INCLUDED #define STRNGBAD_H_INCLU

《modern operating system》 chapter 3 MEMORY MANAGEMENT 笔记

MEMORY MANAGEMENT The part of the operating system that manages (part of) the memory hierarchy is called thememory manager 这章感觉有点多...80 多页..看完都看了两天多,做笔记就更有点不想...有点懒了..但是要坚持下去,可以自己较劲 对于内存的抽象,最简单的抽象就是...没有抽象 和第一次看不一样,把summary放在最前面,对整个mamory management的

System and method for parallel execution of memory transactions using multiple memory models, including SSO, TSO, PSO and RMO

A data processor supports the use of multiple memory models by computer programs. At a device external to a data processor, such as a memory controller, memory transactions requests are received from the data processor. Each memory transaction reques

Cpp Chapter 13: Class Inheritance Part1

class inheritance lets you derive new classes from old ones, inheriting its properties of the old class, called the base class With inheritance, you can: 1 add functionality to existing classes 2 add the data a class represents 3 modify how a class m

Cpp Chapter 14: Reusing code in C++ Part1

14.1 Classes with object members ) The valarray class To declare an object, you follow the identifier valuearray with angle brackets that contain the desired type: valarray<int> q_values; valarray<double> weights; Several examples that use the