C++ 系列存储持续性、作用域、链接性

408 阅读5分钟

ISO_C++_Logo.svg.png

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

对于一个真实的c++项目来说会有成百上千个文件,而文件中又有多个函数、类、变量。有些变量我们想让它在多个文件中共用,有些变量我们只想使它的生效范围在一个文件里,或者更小一点在一个代码块中,随着代码块的结束,在代码块中声明的变量也随之被释放,那么我们如何使这些变量各施其职呢,如何使它们的名称不会产生冲突呢,这就是我们要学习的变量的存储持续性、作用域、链接性。

作用域

  • 作用域指的是一个变量在文件多大范围内可见,例如函数中定义的变量只能在函数中可见,函数外无法访问该元素

链接性

  • 链接性指的是在一个文件中定义的变量是否可以被其他文件可见和使用,链接性为内部那么变量名称只能在该文件内可见,链接性为外部那么变量名称可以在文件间共享。

存储数据的四种方案

  • 首先我们来看看存储数据的四种方案,如果按在数据在内存中的保留时间来区分

自动存储持续性

  • 默认情况下函数内定义的变量的存储持续性是自动的,这种变量在进入函数时才被分配内存空间,当函数执行结束时,内存空间被自动释放。这种变量的生成和释放由栈来控制。

  • 当一个函数中和它的外层函数定义了相同名称的变量,则根据就近原则,在该函数的范围内内层的变量将隐藏外层的变量。当该函数执行完成后原来的变量定义又变的可见。

静态持续变量

  • 在函数定义外定义的变量和使用static关键字修饰的变量都属于静态变量,它们在程序运行期间都会存在

    • 因为静态变量在程序运行期间都是存在的,因此不需要使用栈去存储它们,编译器将分配单独的空间去存储它们。
    • 静态变量的初始化默认都被设置为0
    • 静态变量的初始化值可以是常数值或者可计算的表达式,如果表达式中的值涉及到别的文件中的函数那么这被叫做动态初始化,动态初始化将在编译后完成。

在静态持续变中根据链接性又可以分为静态持续性-外部链接性静态持续性-内部链接性无链接性

静态持续性-外部链接性

  • 在函数外定义的并且不使用static关键字修饰的变量具有外部链接性,这意味着在别的文件中是可以使用该变量的,这对于编写程序有着很大的便利。

      -#include<iostream>
      
       int x=10; // 这样定义的变量具有外部链接性
       
       int main() {
       
       }
      
    
  • 单定义规则

    • 一方面在每一个使用外部变量的文件中都要对该变量进行声明,另外一方面根据c++的单定义规则,变量只允许被定义一次,因此在c++中出现两种定义,一种是定义声明,它会为变量分配存储空间。另一种是引用声明,它不会为变量分配存储空间,因为它实际上引用的就是已有的变量
    • 如果在文件中定义的是具有外部链接性的静态持续变量,那么为了避免在不同文件中重复定义变量,但是为了使该变量可以使用引用声明,它不会导致分配存储空间。 引用声明的关键字是 extern
      -   例子: extern int x;
    
  • 如果我们在函数中声明了一个与外部变量同名的变量,在通常情况下函数内声明的变量会隐藏外部的变量,如果你想使用外部变量,可以使用作用域解析运算符(::) 就可以在函数内使用外部变量。

静态持续性-内部链接性

  • 当static限定符用于作用域为整个文件的变量的时候,那么该变量的链接性是内部的,这意味着该变量可以在文件的任何地方被使用(除了函数内有同名的变量将外部变量隐藏),同时在别的文件中将无法使用该变量。

  • 再别的文件中同样可以在定义相同名称的变量例如:

      - file1:
        static int x = 20;
        
      - file2:
        int x = 20;
        
       //以上是被允许的
       
       file1:
       int x = 20;
       
       file2:
       int x = 10;
       
       //上面这部分是会报错的,因为根据单定义规则它对变量x重复分配了空间
       
    

静态持续性-无链接性

  • 这种变量是局部变量,它被定义在代码块中,由static限定符修饰。这种变量说是局部的变量但是不会随着函数的消亡而被销毁,它还是会存在,并且它只会初始化一次,当函数再次调用时它的值不会自动改变,它适合记录函数调用的次数,被函数用来传递状态。