C C++ static关键字详解(最全解析,static是什么,static如何使用

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

{
test();
i++;
}
return 0;
}


        输出结果变成了:1 2 3 4 5 6 7 8 9 10  
         **原因是static修饰了局部变量x,令局部变量x变成静态的,且只能初始化一次,使得每次test()函数结束时局部变量x都不销毁,再次进入test()函数时则保留原有数值运行,因此x++数值越来越大。**  
![](https://img-blog.csdnimg.cn/d60a2f0fc17e409d8aca5cddce86b02b.png)



**⭐总结:**


**(1)static关键字修饰局部变量不改变作用域,但是生命周期变长。**


**(2)本质上,static关键字修饰局部变量,改变了局部变量的存储位置,因为存储位置的差异,使得执行效果不一样。普通的局部变量放在栈区,这种局部变量进入作用域创建,出作用域释放。局部变量被static修饰后成为静态局部变量,这种变量放在静态区,创建好后,直到程序结束后才释放。**  
  



4️⃣:static 关键字 没有赋值时,默认赋值为 0

接下来用们用一段代码来进行解析:

int a;
int main()
{
	char str[10];
	printf("integer: %d; string: (begin)%s(end)\n", a, str);
	return 0;
}

在这段代码中,我们并没有对全局变量 a 和字符串数组 str 进行赋值,所以在输出时会出现随机值的现象。所以很容易得到如下的结果:

输出:

integer: 0; string: (begin)烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫烫攼l(end)

⚠ 注意:a 输出为 0 是因为 此时 a 是全局变量,也存放在静态区,所以可以默认值为 0 .


接着我们用上 static关键字 来修饰 全局变量 a 和字符串数组 str

static int a;
int main()
{
	static char str[10];
	printf("integer: %d; string: (begin)%s(end)\n", a, str);
	return 0;
}

输出:

integer: 0; string: (begin)(end)

⭐总结:

static的另一个作用是默认初始化为0。其实全局变量也具备这一属性,因为全局变量也存储在静态数据区。在静态数据区,内存中所有的字节默认值都是0x00,某些时候这一特点可以减少程序员的工作量。比如初始化一个稀疏矩阵,我们可以一个一个地把所有元素都置0,然后把不是0的几个元素赋值。如果定义成静态的,就省去了一开始置0的操作。再比如要把一个字符数组当字符串来用,但又觉得每次在字符数组末尾加‘\0’;太麻烦。如果把字符串定义成静态的,就省去了这个麻烦,因为那里本来就是 ‘\0’。

💦static在修饰局部变量和函数的作用

⭐作用:

保持变量内容的持久

  • static的第一个作用是保持变量内容的持久,即static变量中的记忆功能和全局生存期。
  • 存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。之后再次运行到含有 static 关键字的初始化语句时不会再执行该语句。共有两种变量存储在静态存储区:全局变量和 static 变量,只不过和全局变量比起来,static 可以控制变量的可见范围。

🍓static修饰全局变量和函数

3️⃣ :在全局和/或命名空间范围 (在单个文件范围内声明变量或函数时) static 关键字指定变量或函数为内部链接,即外部文件无法引用该变量或函数。

针对上面这个概念的理解我们一次来解析以下:

  1. 首先说一下全局变量,全局变量的作用域十分的广,只要在一个源文件中定义后,这个程序中的所有源文件、对象以及函数都可以调用,生命周期更是贯穿整个程序。文件中的全局变量想要被另一个文件使用时就需要进行外部声明(以下用extern关键字进行声明)。----**-**也即是说全局变量既可以在源文件中使用,也可以在其他文件中使用(只需要使用extern外部链接以下即可)

  2. static修饰全局变量和函数时,会改变全局变量和函数的链接属性-------变为只能在内部链接,从而使得全局变量的作用域变小。

接着我们用代码进行解析:

首先,在Hello.c文件中定义一个全局变量 char a 和函数 PrintfHello(),之后在test.c文件中进行extern 进行外部链接,运行代码:

之后我们进入正题 在全局变量和函数之前用 static进行修饰,看看效果:

会发现生成错误,无法解析外部符号a和PrintfHello()等,全局变量a和PrintfHello()不能被test.c文件调用了。所以我们可以很容易看出static修饰后让全局变量a和PrintfHello()的作用域变小了,令全局变量a和PrintfHello()无法被其他文件调用。

⭐总结:

  1. 全局变量和函数本身是具有外部链接属性的,在Hello.c文件中定义的全局变量和函数,在test.c文件中可以通过**【链接】**来使用;

  2. 但如果全局变量被static修饰,那这个外部链接属性就会被修改成内部链接属性此时这个全局变量就只能在自己的源文件中使用;

💦static在修饰全局变量和函数的作用

⭐作用:
        如果加了 static,就会对其它源文件隐藏。例如在 a 和 printHello 的定义前加上 static,main.c 就看不到它们了。利用这一特性可以在不同的文件中定义同名函数和同名变量,而不必担心命名冲突。static 可以修饰函数和变量,将其对其他源文件隐藏起来,从而避免命名冲突。对于函数来讲,static 的作用仅限于该隐藏功能。

五、C++中的 static

本小节主要介绍在 C++中引入了面向对象的特性(类)之后,static关键字的一些用途。当然 C++ 是兼容 C 语言的,所以C语言中的 static 在C++中也是成立的

🍌static的C++用法

声明为static的类成员称为类的静态成员,分为如下两类:

  • 用static修饰的成员变量,称之为静态成员变量
  • 用static修饰的成员函数,称之为静态成员函数

静态的成员变量一定要在类外进行初始化

🍊static在C++中的重点概念

1️⃣:静态成员为所有类对象所共享,不属于某个具体的实例
2️⃣:静态成员变量必须在类外定义,定义时不添加static关键字
3️⃣:静态成员函数没有隐藏的this指针,不能访问任何非静态成员
4️⃣:访问静态成员变量的特殊方式

5️⃣:静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值

⭐:接下来,将重点讲解上面三个作用个五点概念的理解,和应用

💦静态成员为所有类对象所共享,不属于某个具体的实例

请看如下代码:

class A
{
private:
	static int _n;
	int _k;
	char _a;
};
int main()
{
	cout << sizeof(A) << endl; //8
	return 0;
}

这里的运行结果为8,这里的计算规则是按照C语言那套计算结构体大小的规则。并没有把我静态成员变量_n考虑进去,因为静态成员变量属于整个类,是类的所以对象,所以静态变量成员不计入总大小。

💦静态成员变量必须在类外定义,定义时不添加static关键字
class A
{
private:
	//声明
	static int _n;
	static int _k;
};
//定义
int A::_n = 0;
int A::_k = 0;
💦静态成员函数没有隐藏的this指针,不能访问任何非静态成员
class A
{
public:
	static void Func()
	{
		cout << ret << endl;  // err错误,访问了非静态成员,因为无this指针
		cout << _k << endl; //正确
	}
private:
	//声明
	int ret = 0;
	static int _k;
};
//定义
int A::_k = 0;
💦访问静态成员变量的特殊方式

当静态成员变量为公有时,可有如下三种进行访问:

  1. 通过对象.静态成员来访问
  2. 通过类名::静态成员来行访问
  3. 通过匿名对象突破类域进行访问
class A
{
public:
// 声明
	static int _k;
};
// 定义
int A::_k = 0;
int main()
{
	A a;
	cout << a._k << endl;  //通过对象.静态成员来访问
	cout << A::_k << endl; //通过类名::静态成员来行访问
	cout << A()._k << endl;//通过匿名对象突破类域进行访问
	return 0;
}

当静态成员变量变成私有时,可采用如下方式:

  1. 通过对象.静态成员函数来访问
  2. 通过类名::静态成员函数来行访问
  3. 通过匿名对象调用成员函数进行访问
class A
{
public:
	static int GetK()
	{
		return _k;
	}
private:
	static int _k;
};
int A::_k = 0;
int main()
{
	A a;
	cout << a.GetK() << endl; //通过对象.静态成员函数来访问
	cout << A::GetK() << endl;//通过类名::静态成员函数来行访问
	cout << A().GetK << endl; //通过匿名对象调用成员函数进行访问
	return 0;
}
💦静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值
  • 1、静态成员函数可以调用非静态成员函数吗?

答案:不可以,因为静态成员函数是没有this指针的,无法调用非静态成员函数。

  • 2、非静态成员函数可以调用类的静态成员函数吗?

答案:可以,因为静态成员为所有类对象所共享,不受访问限制

六、static面试题

搞清楚了static的特性,来看几道道面试题:

面试题1:

实现一个类,计算中程序中创建出了多少个类对象。

  • 思路:

假设命名该类为A,那么A类型的对象一定是经过构造函数或拷贝构造的,那么我们就可以分别定义两个静态成员变量,在构造函数和拷贝构造里++变量,这样,每创建一次对象,变量就++一次,自然就好求了。如下:

class A
{
public:
	A()
	{
		++_count1;
	}
	A(const A& aa)
	{
		++_count2;
	}
	static int GetCount1()
	{
		return _count1;
	}
	static int GetCount2()
	{
		return _count2;
	}
private:
	static int _count1; 
	static int _count2;
};
int A::_count1 = 0;
int A::_count2 = 0;
A Func(A a)
{
	A copy(a);
	return copy;
}
int main()
{
	A a1;
	A a2 = Func(a1);
 
	cout << a1.GetCount1() << endl; // 1
	cout << a2.GetCount2() << endl; // 3
	cout << A::GetCount1() + A::GetCount2() << endl; // 4
}
  • 分析:

A a1 调用了一次构造函数;a2 = Func(a1),调用了一次拷贝构造;A copy(a),调用了一次拷贝构造;return copy 返回的时候,copy会销毁,所以提前需要进行拷贝构造进行拷贝保存 。所用总共四次。

七、static OJ面试题

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

A a1 调用了一次构造函数;a2 = Func(a1),调用了一次拷贝构造;A copy(a),调用了一次拷贝构造;return copy 返回的时候,copy会销毁,所以提前需要进行拷贝构造进行拷贝保存 。所用总共四次。

七、static OJ面试题

[外链图片转存中…(img-z0OXRAHz-1715679987168)]
[外链图片转存中…(img-BpRxQgea-1715679987168)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 28
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: static关键字在C/C++中有多种用法。它可以用来修饰函数和变量,控制它们的存储方式和作用范围。在函数内部声明的static变量是静态局部变量,它在函数调用结束后仍然保留其值,且只能在声明它的函数中访问。在全局作用域中声明的static变量是静态全局变量,它只能在声明它的文件中访问,不能被其他文件访问。在C++中,static还可以修饰类的成员,包括静态成员变量和静态成员函数。静态成员变量是类的所有实例共享的变量,静态成员函数则可以直接通过类名调用,不需要实例化对象。总结来说,static关键字在C/C++中有多种用途,用来修饰函数和变量的存储方式和作用范围。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [在 C/C++static 关键字详解](https://blog.csdn.net/weixin_45910068/article/details/123621193)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [C++ static关键字](https://blog.csdn.net/weixin_44966641/article/details/122149739)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值