C++PrimerPlus学习之内存模型和名称空间

版权声明:转载之前请说你是博主的粉丝哦。 https://blog.csdn.net/qq_34921856/article/details/83548037

头文件

  • 如果文件名包含在尖括号中,则C++编译器将在存储标准头文件的主机系统的文件系统的中查找。如果文件名包含在双引号中,则编译器将在当前目录下查找。

  • 使用条件编译防止多次包含头文件

    #ifndef XXX_H_
    #define XXX_H_
    
    ...
    
    #endif
    

存储持续性,作用域和链接性


存储描述 持续性 作用域 链接性 如何声明 存储位置
自动 自动 代码块 在代码块中 栈中
寄存器 自动 代码块 在代码块中,使用关键字register 寄存器中
静态,无链接性 静态 代码块 在代码块中,使用关键字static 内存块
静态,外部链接性 静态 所有文件 外部 不在任何函数中 内存块
静态,内部链接性 静态 本文件 内部 不在任何函数内,使用关键字static 内存块
  • 如果定义一个静态外部链接性的变量,其他文件在使用时,需要引用声明使用关键字extern,且不进行初始化。

  • 作用域解析运算符

    int a=5;
    int main()
    {
        int a=3;
        cout<<a<<endl;
        cout<<::a<<endl;//作用域解析运算符,此时的a为全局变量的a
    }
    
  • 说明符

    • register 用于在声明中指示寄存器存储,而在C++11中,它只是显式地指出变量是自动的。
    • static 表示内部链接性。
    • extern 表面是引用声明,即声明引用在其他文件定义的变量。
    • thread_local(C++11新增) 指出变量的持续性与其所属的线程的持续性相同。thread_local变量之于线程,犹如常规静态变量之于整个程序。
    • mutable 用来指出,即使结构(或类)变量为const,其某个成员也可以被修改。
    struct student
    {
        char name[30];
        mutable int score;
    };
    int main()
    {
        const student a={"guo shen",100};
        a.score++;
        cout<<a.name<<' '<<a.score<<endl;
    }
    
  • cv-限定符

    • volatile
      • 即使程序代码没有对内存单元进行修改,其值也可能发生变化(可能受硬件影响)
      • 如果不使用volatile变量,在再次访问之间编译器可能会认为值没有变化,从而进行优化(如将值放在寄存器中缓存起来)
      • 使用volatile变量相当于告诉编译器,不要进行这种优化
    • const – 不能修改的内存
      • const 对全局变量的链接性有影响 – const全局变量的链接性为内部的。
      • 这也是const变量能写在头文件而没有多重定义的原因
      • 若想使用链接性为外部的const变量,则可以再在前面加extern进行定义,但其他文件使用此变量必须也要用extern关键字进行声明
    extern const int maxn = 100;
    
  • 函数的链接性

    • 函数默认为外部静态的 即默认是extern的
    • 可使用 static 关键字将其链接性设置为内部的
      • 必须同时在原型和定义中使用static
      • 内部静态函数将覆盖外部函数
  • 语言链接性

    • C语言对函数名的矫正使用的约定与C++不同, 可用函数原型指出其使用的约定
    extern "C" void fun(int);   // 使用C语言的约定
    extern void fun(int);     // 使用C++的约定
    extern "C++" void fun(int); // 使用C++的约定 -- 显式指出
    
  • 动态分配内存

  • new运算符

    void * operator new(size_t); //used by new
    void * operator new[](size_t);//used by new[]
    
  • 定位new运算符

    • new 负责在堆上找一块满足要求的内存块
    • 定位new 能指定要使用的位置
      • 设置内存管理规程,处理需要通过特定地址进行访问的硬件,在特定位置创建对象等
    • 使用
    #include <new>
    char buff[50];
    int* p = new (buff) int[20]; // 从buff中分配一个包含20个int的数组
    //不能使用delete来释放内存
    void* operator new(std::size_t, void* position);//定位new运算符的重载
    

名称空间

  • using 编译指令和using声明之比较

    • 如果某个名称已经在函数声明了,则不能用using声明导入相同的名称。
    • 如果使用using编译指令,名称空间相当于全局的,那么局部名称将隐藏名称空间名,就像隐藏同名的全局变量一样。不过仍可以使用作用域解析运算符。
  • 未命名的名称空间

    namespace
    {
        int cnt=5;
    }
    //=static int cnt=5;
    int main()
    {
        cout<<cnt<<endl;
    }
    

猜你喜欢

转载自blog.csdn.net/qq_34921856/article/details/83548037