当前位置:   article > 正文

C++:静态变量_c++静态变量

c++静态变量

一、类或结构体外部静态变量

  1. 静态变量的初始化和空间释放:全局静态变量是在软件刚运行时就初始化,局部静态变量是在软件运行到那一块代码时才初始化。无论全局还是局部静态变量都是在程序运行结束后释放空间。
  2. 静态变量的空间是放在静态存储区的,初始化一个含有静态变量的类实例时,该实例的大小是不包含静态变量的空间的;sizeof(ClassName),使用类名查看大小也是不包含静态变量的

1.1 外部静态变量

static int s_StVariable = 0;

class StaticClass {
public:
	int m_Varible;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

变量s_StVariable 为定义在类外部的静态变量。
在类的外部声明为静态变量时,只有编译器在编译该翻译单元的时候才会识别到。链接器在链接其他翻译单元时,对其他的翻译单元而言,s_StVariable 这个静态变量是不可见的。

这样也就是我们常说的,静态变量只有在自己定义的.cpp文件中才会有效的原因。类中时有public,private之类的访问权限控制。我们如果把一个.cpp(翻译单元)看成是一个类的话,外部的static声明就是相当于定义这个变量或者函数为private。

1.2 全局变量

如果我们声明变量s_StVariable 时候不加static修饰,即

int s_StVariable = 0;

class StaticClass {
public:
	int m_Varible;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

那么s_StVariable 就是一个全局的变量,全局是指在链接器连接的时候任何翻译单元都可以访问这个变量,即这个变量对于其他的翻译单元来说是Public的。一般我们不建议这样使用,全局变量很容易出现冲突。

1.3 extern外部变量

和类外的static变量相似的,还有另外一个关键字extern;

extern int e_Varible;
class StaticClass {
public:
	int m_Varible;
};
  • 1
  • 2
  • 3
  • 4
  • 5

static关键字声明的变量是告诉编译器,这个变量是该翻译单元(.cpp)私有的,链接器查找时只有定义该变量的翻译单元可以使用,其他的翻译单元不可见该变量。
extern声明的变量是告诉链接器去其他的翻译单元中查找这个变量,即我在另一个cpp文件中定义一个全局变量int e_Varible 。在本文件内用extern做一个声明,我就可以使用另一个文件的全局变量。如果不加extern则会出现重定义冲突。加上extern后的变量相当于函数的函数声明。

1.4 头文件中的静态变量

一般情况下我们可能会选择在一个公共的.h头文件中定义一堆的全局静态变量,用于其他的cpp文件中,做配置信息。在其他的cpp文件将这个.h包含进去的时候,其实就是相当于在自己的cpp中定义了一个静态变量,多个cpp就是每一个文件中都有一个私有的静态变量。
当然.h中定义静态变量一般我们都会声明为const,不能修改,防止不同的cpp修改后变量值不同步。

二、类或结构体内部静态变量

2.1 静态成员变量

class StaticClass {
public:
	static int m_Varible;
	static void Print() {
		std::cout << m_Varible;
	}
	int m_x, m_y;
};
int StaticClass::m_Varible = 0;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

成员变量m_Varible为我们定义在类内部的静态变量。类内部的静态变量作用就是让该类的所有实例对象有一个共用的数据变量,实现所有实例对象之间的公用数据同步。

静态成员变量定义在类的内部,但是类的外部必须有其对应的初始化。

2.2 静态成员函数

static void Print()函数为定义在类内部的静态成员函数,默认情况下,静态成员函数只能访问静态成员变量。但是我们如果想要静态成员函数访问类实例先关的数据时也是可以做到的。

class StaticClass {
public:
	static int m_Varible;
	static void Print(StaticClass &var) {
		std::cout << var.m_x;
	}

	int m_x, m_y;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

只需要将对应实例变量的引用传递进来就可以使用。实际上我们调用普通的类成员变量的时候编译器最终执行的函数就是和上面定义的print是一致的。每一个类成员函数都是有一个指向自己的指针的对象的,只不过代码上我们看不到而已。

三、静态局部变量

静态局部变量的生存周期是从该变量被定义开始一直到程序结束为止。作用域是定义改变量所在的代码块内。
关于生存周期的解释见:

https://blog.csdn.net/bareheadedman/article/details/100020896

一般静态局部变量我们都是定义在函数内部,当我们第一次调用该函数时,这个变量被初始化,函数结束时该局部静态变量并不会被销毁,下一次当我们再次调用这个函数时,不会重新创建一个新的变量,而是使用首次调用生成的那个变量。

我们可以使用此特性实现一个单例类,来简化我们单例模式的实现:

class Singleton {
	Singleton() {};

public:
	Singleton& GetInstance() {
		static Singleton instance;//存放一个局部静态变量,多次调用也只有一个实例对象
		return instance;
	}
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/469802
推荐阅读
相关标签
  

闽ICP备14008679号