• 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.
    ";
        update(0.1);
        cout << "Global warming is " << warming << " degrees.
    ";
        local();
        cout << "Global warming is " << warming << " degrees.
    ";
        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.
    ";
    }
    
    void local()
    {
        double warming = 0.8; // use local varaible
        cout << "Local warming = " << warming << " degrees.
    ";
        cout << "But global warming = " << ::warming << " degrees.
    "; // 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:
    ";
        cout << &tom << " = &tom, " << &dick << " = &dick, " << &harry << " = &harry
    ";
        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:
    ";
        cout << &tom << " = &tom, " << &dick << " = &dick, " << &harry << " = &harry
    ";
    }
    

    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:
    ";
        cin.get(input, ArSize);
        while (cin)
        {
            cin.get(next);
            while (next != '
    ')
                cin.get(next);
            strcount(input);
            cout << "Enter next line(empty line to quit):
    ";
            cin.get(input, ArSize);
        }
        cout << "Bye
    ";
        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
    " << total << " characters total
    ";
    }
    

    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 with file-scope declaration indicates internal linkage, 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
    

  • 相关阅读:
    存储过程output String[1]: Size 属性具有无效大小值0
    深入理解JS异步编程四(HTML5 Web Worker)
    深入理解JS异步编程三(promise)
    深入理解JS异步编程二(分布式事件)
    深入理解JS异步编程(一)
    不定高多行溢出文本省略
    深入解析js中基本数据类型与引用类型,函数参数传递的区别
    javascript的replace+正则 实现ES6的字符串模版
    从输入网址到显示网页的全过程分析
    WebStorage 和 Cookie的区别
  • 原文地址:https://www.cnblogs.com/fsbblogs/p/9745910.html
Copyright © 2020-2023  润新知