第9章 内存模型和名称空间

【摘要】 9.1 单独编译
头文件中常包含的内容:
函数原型

使用#define或const定义的常量

结构声明

类声明

模板声明

内联函数

头文件防护
9.2 存储持续性、作用域、链接性
存储持续性
自动存储持续性

静态存储持续性 : 在程序整个运行过程中都在

9.1 单独编译

头文件中常包含的内容:

函数原型
使用#define或const定义的常量
结构声明
类声明
模板声明
内联函数

头文件防护

9.2 存储持续性、作用域、链接性

存储持续性

自动存储持续性
静态存储持续性 : 在程序整个运行过程中都在
线程存储持续性
动态存储持续性 : new创建,delete释放

自动存储持续性
· 没有链接性
1、自动变量的初始化
2、自动变量和栈
3、寄存器变量

register int count_fast;
//在C++11中只是显式地指出变量是自动的。
//目前使用它的唯一原因是,指出程序员想使用一个自动变量,这个变量可能与外部变量名称相同

  
 

静态持续变量

有三种链接性

外部链接性(可在其他文件中访问)
  在代码块外面声明,不用加static关键字 在其他文件中使用外部变量,只需要在一个文件中定义,在其他文件中,使用extern声明
  ::warming,::作用域解析运算符放在变量名前边时,表示使用该变量的全局版本

    
   
内部链接性(只能在当前文件中访问)
  在代码块外面声明,需要加static关键字 在两个文件中可以定义两个名称相同的变量,不违反当定义原则

    
   
无链接性(只能在当前函数或代码块中访问)
  在代码块内部声明,需要加static关键字 如果初始化了静态局部变量,则程序只在启动时进行一次初始化。以后在调用函数时,将不会像自动变量那样再次初始化。

    
   

说明符和限定符

register
static
extern
thread_local
mutable

  
 

thread_local指出变量的持续性与其所属的线程的持续性相同

  1. cv-限定符
    const 和 volatile
    volatile 表明即使代码没有对内存单元进行修改,其值也可能发生变化。

  2. mutable
    表明即使结构(或类)变量为const,其某个成员也可以被修改。

  3. const
    在默认情况下全局变量的链接性是外部的,但const全局变量的链接性为内部。(因此可以放在头文件中)
    如果想要外部链接性,可在定义时使用extern来覆盖默认的内部链接性

函数和链接性
所有函数的储存持续性都自动为静态的,默认链接性外部
使用该函数必须包含该函数原型

可以使用static将函数的链接性设置为内部的,使之只能在一个文件中使用。必须同时在原型和函数定义中使用

static int private(double x);
static int private(double x){
	cout << "private" << endl;
}

  
 

内联函数不受单定义规则的约束,这允许程序员能够将内联函数的定义放在头文件中。

语言链接性

extern "C" void spiff(int);//使用C语言链接性
extern void spoff(int); //使用C++链接性
extern "C++" void spaff(int);//使用C++链接性

  
 

存储方案和动态分配
前面方案不适合动态内存分配,其分配和释放顺序要取决于new和delete在何时以何种方式被使用。
通常编译器使用三块独立的内存:自动变量、静态变量、动态存储

extern float * p_fees;
//可以在其他函数中使用当前指针

  
 
  1. 使用new进行初始化
    int *pi = new int (6); //小括号可以赋初始值
    double * pd = new double (99.99);
    
    //列表初始化 常规结构或者数组
    struct where{double x; double y; double z;}
    where * one  = new where {2.5, 4.5, 4,4};
    int * ar = new int [4] {2,4,6,7};
    int * pin = new int {6};//单值也可以
    
        
       
  2. new失败时
    引发异常 std::bad_alloc
  3. new:运算符、函数和替换函数
    // 分配函数
    // new和new [] 分别调用如下函数
    void * operator new (std::size_t);
    void * operator new[](std::size_t);
    
    // 释放函数
    // delete 和 delete [] 分别使用如下函数
    void operator delete (void *);
    void operator delete [](void *);
    
        
       
  4. 定位new运算符
    new运算符的变体,可以指定要使用的位置。
    #include <new>
    char buffer1[50];
    int main({
    	int *p4 = new (buffer1) int[20];
    }
    
        
       

void 指针可以指向任意类型的数据,就是说可以用任意类型的指针对 void 指针对 void 指针赋值。例如:

int *a;
void *p;
p=a;

  
 
  1. 定位new的其他形式
    int* p1 = new int;
    int* p2 = new(buffer) int;
    int* p3 - new(buffer) int[40];
    
        
       

9.3 名称空间

概念:声明区域、潜在作用域、作用域

名称空间可以是全局的,也可以位于另一个名称空间中,但不能位于代码块中,因此在默认情况下,在名称空间中声明的名称的链接性为外部的(除非他引用了常量)。

通过域解析运算符::,使用名称空间来限定该名称。

  1. using 声明和using 编译指令
  2. 为名称空间创建别名
    namespace mvft = my_very_favorite_things;
    
        
       
  3. 未命名的名称空间
    namespace{
    	int ice;
    	int bandycoot;
    }
    
        
       

    这种方式是链接性为内部的静态变量的替代品

文章来源: blog.csdn.net,作者:Miical,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/m0_50998563/article/details/116171596

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享