C++:静态变量

文章详细阐述了C++中不同类型的静态变量,包括类或结构体外部的静态变量、全局变量、extern变量,以及类内部的静态成员变量和静态成员函数。静态变量的生命周期和作用域是其关键特性,而静态局部变量则在函数调用中保持其值。此外,文章还提到了静态变量在实现单例模式中的应用。
摘要由CSDN通过智能技术生成

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

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

1.1 外部静态变量

static int s_StVariable = 0;

class StaticClass {
public:
	int m_Varible;
};

变量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;
};

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

1.3 extern外部变量

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

extern int e_Varible;
class StaticClass {
public:
	int m_Varible;
};

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;

成员变量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;
};

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

三、静态局部变量

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

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

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

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

class Singleton {
	Singleton() {};

public:
	Singleton& GetInstance() {
		static Singleton instance;//存放一个局部静态变量,多次调用也只有一个实例对象
		return instance;
	}
};
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值