Cpp Chapter 9: Memory Models and Namespaces Part2

來源:互聯網
上載者:User

標籤:oid   names   repo   hat   als   better   with   one   port   

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 0extern int down; // declaration, down should be defined elsewhereextern 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.cppextern int cats = 20; // definitionint dogs = 22; // definitionint fleas; // definition// file02.cppextern int cats; // declaration, cats defines in file01extern int dogs; // declaration, dogs defines in file01//file98.cppextern 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 definitionvoid 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.cppvoid 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:

// file1int errors = 20; // external definition// file2static int errors = 10; // internal definition, don‘t contradict with file1static double thing = 6.5; // internal definitioncout << errors; // the answer should be 10// file3double thing = 6.7; // external definition, don‘t contradict with file2cout << 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 definitionint dick = 30; // external definitionstatic int harry = 300; // internal definitionvoid 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.cppstatic int dick = 10; // internal definition; overrides external dick in twofile1.cppint harry; // external definition; no conflict with twofile1.cpp‘s internal harryvoid 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 structureveep.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-upextern void spoff(int); // use C++ protocol for name look-upextern "C++" void spaff(int); // use C++ protocol for name look-up

Cpp Chapter 9: Memory Models and Namespaces Part2

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.