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

头文件

  • 如果文件名包含在尖括号中,则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;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值