🐯2.4 使用局部静态对象

何时需要局部静态变量

:::info 我们知道在函数内部定义的变量,当程序执行到它的定义处时,编译器为它在栈上分配空间,函数在栈上分配的空间在此函数执行结束时会释放掉,这样就产生了一个问题: 如果想将函数中此变量的值保存至下一次调用时,如何实现? 最容易想到的方法是定义为全局的变量,但定义一个全局变量有许多缺点,最明显的缺点是破坏了此变量的访问范围(使得在此函数中定义的变量,不仅仅只受此函数控制)。static 关键字则可以很好的解决这个问题。
另外,在 C++ 中,需要一个数据对象为整个类而非某个对象服务,同时又力求不破坏类的封装性,即要求此成员隐藏在类的内部,对外不可见时,可将其定义为静态数据。 :::

  • 当函数内变量需要多次调用,且其值并不随每次调用改变;
  • 或者是需要记录每次的值;

与局部非静态对象不同的是,局部静态对象所处的内存空间,即使在不同函数的调用过程中,依然持续存在,不会每次调用函数就会被破坏然后重新建立;

*🐋 C++ 存储类

存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前。下面列出 C++ 程序中可用的存储类:
:::tips

  • auto
  • register
  • static
  • extern
  • mutable
  • thread_local (C++11) ::: 从 C++ 17 开始,auto 关键字不再是 C++ 存储类说明符,且 register 关键字被弃用。

static

static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值。
static 修饰符也可以应用于全局变量。当 static 修饰全局变量时,会使变量的作用域限制在声明它的文件内。
在 C++ 中,当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享。

extern

extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当使用 ‘extern’ 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。
当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。可以这么理解,extern 是用来在另一个文件中声明一个全局变量或函数。 :::tips extern 修饰符通常用于当有两个或多个文件共享相同的全局变量或函数的时候 :::

thread_local

使用 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。
可以将 thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。

🦒2.5 声明inline函数

只要在函数前加上inline就可以将函数声明为内联函数: inline bool fibon_elem(int pos, int &elem)
将函数声明为inline,表示要求编译器在每个函数调用点上都将函数完全展开。面对一个inline函数,编译器可以将该函数的调用操作改成一份函数代码副本来替代,是的性能得到改善。

  • 将函数指明为inline是一种请求而编译器并非一定会执行。适合声明为inline的函数往往体积小、反复被调用、计算不复杂。
  • inline函数的定义常常放在头文件中。

小结

  • 局部静态对象不会在每次调用后被销毁
  • 当 static 用在类数据成员上时,会导致仅有一个该成员的副本被类的所有对象共享