static关键字详解(C/C++)

前言

static关键字在C/C++/JAVA编程语言中都存在,而且在编程中经常会遇到,那么,在C/C++中,static究竟意味着什么?那么static修饰的变量和函数有什么样的特点呢?

本篇内容提要:
在这里插入图片描述

可以说,所有的静态变量都有几个共同特点:

  1. 在main函数执行之前就分配了内存(分配在全局数据区),整个程序执行完才会被销毁;
  2. 若没有初始化,会被程序自动初始化为0

1.静态局部变量

一般的局部变量有一个问题,就是生命周期短,所以我们经常会定义全局变量,但是在实际的开发中,若全局变量定义太多,很容易出现重名的问题,而且也不容易区分,所以在一般的开发中,并不会定义过多的全局变量。

静态局部变量同时具备局部变量的防重复和生命周期长两个优点,可以很好地解决这个问题。
比方说:

#include <iostream>
void print_fun()
{
    
    
	static int a = 0;
	a++;
	printf("a = %d\t", a);
}
int main()
{
    
    
	int add = 0;
	while (add < 10)
	{
    
    
		print_fun();
		add++;
	}
	printf("\n");
}

打印输出:
在这里插入图片描述

从以上这个简单的例子,就可以说明问题。

2.静态全局变量

与局部静态变量类似,只不过静态全局变量虽然也是全部变量,但是仅限在本文件中使用。例如;
mian.cpp文件中程序如下:

#include <iostream>
extern short ex;
int main()
{
    
    
	printf("%d\n", ex);
}

而在example.c文件中,程序如下:

#include <iostream>

static short ex = 0;

运行,出现如下问题:
在这里插入图片描述
可以看出,被static修饰的全局变量,仅仅作用在本文件中,其他文件中无法使用。

3.静态函数

静态函数相对来说比较简单,同样是对外不可见的。例如;
mian.cpp文件中编写程序如下:

#include <iostream>
#include "example.h"
int main()
{
    
    
	static_print_ex();
}

example.h中编写程序如下:

#pragma once
extern short ex;
static void static_print_ex();

example.cpp中编写程序如下:

#include <iostream>
#include "example.h"

static void static_print_ex()
{
    
    
	printf("The static external function is called!");
}

执行后,出现如下错误:
在这里插入图片描述
而在该函数的声明和定义中去掉static后,再次执行,打印输出如下:
在这里插入图片描述
可以看到,程序可以正常执行,也就是静态函数的应用场景就是:
部分函数只想在本文件中使用,为了避免在其他文件中被使用,就可以采用这样的方法。

这个很好解释,就好比const关键字一样,即使我们知道变量定义的时候知道是常量,不想再二次赋值,但是在后续的开发中,为了防止该变量的值被修改,还是会加上const关键字。

4.静态成员变量

因为静态数据成员在全局数据区分配内存,由本类的所有对象共享,所以,它不属于特定的类对象,不占用对象的内存,而是在所有对象之外分配内存,在没有产生类对象时其作用域就可见。因此,在没有类的实例存在时,静态成员变量就已经存在,我们就可以操作它。例如:

假设有个用户类Userm_Usersum是当前系统中某产品的用户数量,所以在任何实例中,查询用户数量都是一样的,然而当某地的用户数量增加的时候,整个产品总的用户数量也会随之增加。

#include <iostream>

class User
{
    
    
public:
	static int m_Usersum;
	static void SetUsersum(const int sum)
	{
    
    
		m_Usersum = sum;
	}
	static int GetUsersum()
	{
    
    
		return m_Usersum;
	}
};
int User::m_Usersum = 100;
int main()
{
    
    
	User *User1;
	printf("There are %d users!\n", User1->GetUsersum());

	User1->SetUsersum(101);

	User *User2;
	printf("There are %d users!\n", User2->GetUsersum());

	User2->SetUsersum(102);

	printf("There are %d users!\n", User1->GetUsersum());
	printf("There are %d users!\n", User2->GetUsersum());
}

打印输出:
在这里插入图片描述
可以看到,静态成员变量对每个类都是一样的,共享的,因为无论有多少个类,静态成员变量在内存中只有一份,所以无论在哪个实例中修改变量的值,在其他类中获取到的值都是一样的。

然后验证一下在类实例化之前访问静态成员变量。
编写代码如下:

#include <iostream>

class User
{
    
    
public:
	static int m_Usersum;
	static void SetUsersum(const int sum)
	{
    
    
		m_Usersum = sum;
	}
	static int GetUsersum()
	{
    
    
		return m_Usersum;
	}
};
int User::m_Usersum = 100;
int main()
{
    
    
	printf("There are %d users!\n", User::m_Usersum);
}

打印输出:
在这里插入图片描述

可以看到,在类没有实例化的时候,静态成员变量已经初始化成功,我们可以随时访问。

5.静态成员函数

1.与普通函数相比,静态成员函数属于类本身,而不作用于对象,因此它不具有this指针。

这句话如何理解呢?
静态成员函数确实属于类,但是和类的对象关系不大,不会牵扯到类的构造析构当中来,所以也不会有this指针。

关于this指针,网上有这样一段描述:

首先,我们都知道类的成员函数可以访问类的数据(限定符只是限定于类外的一些操作,类内的一切对于成员函数来说都是透明的),那么成员函数如何知道哪个对象的数据成员要被操作呢,原因在于每个对象都拥有一个指针:this指针,通过this指针来访问自己的地址。

2.静态成员函数不能访问非静态成员函数和非静态成员变量

这时候为什么呢?
还是和创建时间有关系,静态成员函数在类的实例化之前就已经存在了,这个时候类还没来得及实例化,根本无法访问非静态成员函数和非静态成员变量。

可以验证一下在类实例化之前访问静态成员函数。

#include <iostream>

class User
{
    
    
public:
	static int m_Usersum;
	static void SetUsersum(const int sum)
	{
    
    
		m_Usersum = sum;
	}
	static int GetUsersum()
	{
    
    
		return m_Usersum;
	}
};
int User::m_Usersum = 100;
int main()
{
    
    
	printf("There are %d users!\n", User::GetUsersum());
}

打印输出:
在这里插入图片描述
可以看到,程序可以正常运行。

参考文献

知乎:C/C++ 中的static关键字
哔哩哔哩:C语言关键字static使用及其注意事项

----------------------------------------------------------------------------------END----------------------------------------------------------------------------------

猜你喜欢

转载自blog.csdn.net/weixin_43719763/article/details/129904588
今日推荐