C/C++:static用法总结
前言:static是C/C++中一个很重要的关键字,最近阅读了很多博客和资料,遂在此对自己的学习笔记进行简单的总结并发表在这里
一、C语言中的static
• 静态全局变量:在全局变量之前加上关键字static,该全局变量就被定义成了一个静态全局变量
特别注意:
1.静态全局变量在内存中的存储位置:静态区(全局区)。 [注]:静态区(全局区)在整个程序运行期间都存在
2.静态全局变量的初始化:未经初始化的静态全局变量会被程序自动初始化为0。 [注]:在C语言中,未经初始化的全局变量的值是任意的;而在C++中,未经初始化的全局变量也会被程序自动初始化为0
3.全局变量和静态全局变量的存储方式是一样的,但不同的是全局变量在整个源代码中都是可以使用的,而静态全局变量只能在当前文件中使用。比如一个程序有3个文件a.cpp、b.cpp和c.cpp,如果在文件a.cpp中定义了一个全局变量x,那么变量x在文件a.cpp、b.cpp和c.cpp中都可以使用;但如果在文件a.cpp中定义了一个静态全局变量y,那么变量y只能在文件a.cpp中使用文件b.cpp和文件c.cpp都不可以使用该静态全局变量y
源文件file1.cpp:
// 文件file1.cpp
int value1=;//全局变量value1
static int value2;//静态全局变量value2,默认初始化为0
......
源文件file2.cpp:
// 文件file2.cpp
extern int value1; //成功:期望使用文件file1中定义的全局变量value1
extern int value2; //错误:期望使用文件file1中定义的静态全局变量value2,但value2是static类型,只能在file1中使用,无法被其他文件使用
......
4.使用静态全局变量的好处:
a.将一个全局变量定义为静态全局变量,相当于让该全局变量对该程序的其他源文件进行了“隐藏”,也就是说该静态全局变量只能在定义它的源文件中使用,而程序的其他源文件则无法访问该变量
b.程序中的其他源文件中可以使用与该静态全局变量同名的变量,而不会发生冲突
5.在C/C++程序中,如果一个全局变量仅仅在单个源文件中使用,则可以将该全局变量修改为静态全局变量,以降低模块间的耦合度
• 静态局部变量:在局部变量之前加上关键字static,该局部变量就被定义成了一个静态局部变量
特别注意:
1.静态局部变量在内存中的存储位置:静态区(全局区)。[注]:普通局部变量在内存中的存储位置为栈区
2.静态局部变量的初始化:未经初始化的静态局部变量会被程序自动初始化为0。[注]:在C/C++中,未经初始化的普通局部变量值是任意的
3.static并没有改变局部变量的作用域。换句话说就是静态局部变量的作用域仍是局部作用域,当定义它的函数或语句块结束的时候,其作用域也就随之结束。 [注]:与之相反,static改变了全局变量的作用域(在声明它的文件之外是不可见的)
4.static虽然没有改变局部变量的作用域,但它改变了局部变量在内存中的存储位置(而static修饰的全局变量在内存中的存储位置则没有被static改变),即从原来的栈区中存放改变为静态区(全局区)中存放。因此静态局部变量在离开其作用域时,并没有像一般局部变量那样被销毁,而是仍驻留在内存中的静态区(全局区)中,直到程序结束,只不过在其离开自己的作用域时,我们无法再对其进行访问。
#include<iostream>
using namespace std;
int count=;
int fun(){
static int count=;
return count--;
}
int main(){
cout<<"Global\tLocal Static"<<endl;
for(int i=;i<=;i++){
cout<<" "<<count++<<"\t "<<fun()<<endl;
}
return ;
}
5.在C/C++中,如果全局变量仅有单个函数访问,则可以将该全局变量改为该函数的静态局部变量,以降低模块间的耦合度
• 静态函数:在函数的返回值类型前加上关键字static,该函数就被定义成了一个静态函数
特别注意:
1.和静态全局变量相似,静态函数只能在声明它的源文件中可见,而不能被该程序的其他源文件所使用。
源文件file1.cpp:
//文件file1.cpp
......
extern void fun1(){......} //定义函数fun1
static void fun2(){......} //定义静态函数fun2
......
源文件file2.cpp:
//文件file2.cpp
......
extern void fun1();//成功:期望使用文件file1.cpp中的函数fun1
extern void fun2();//错误:期望使用文件file1.cpp中的静态函数fun2,但fun2是static类型函数,只能在file1中使用,无法被其他文件使用
2.使用静态函数的好处:
a.在该程序的其他源文件中可以定义和使用与该静态函数同名的函数,而不会发生冲突
b.将一个普通函数定义为函数,相当于让该函数对该程序的其他源文件进行了“隐藏”,也就是说该静态函数只能在定义它的源文件中使用,而程序的其他源文件则无法调用该函数。
c.静态函数会被自动分配在一个一直使用的存储区域,直到程序结束。这样避免了普通函数在调用时的进栈出栈操作,从而提高程序的运行速度
• 总结:static在C语言中的作用:
——隐藏功能:static修饰的全局变量和普通函数只能在定义它们的源文件中使用,相当于对程序中的其他源文件进行了隐藏
——默认初始化功能:static修饰的变量,不管是全局变量还是局部变量,在用户没有显式初始化它们的条件下,系统都会将他们默认初始化为0
——延长“寿命”功能:static修饰的局部变量存储在内存的静态区(全局区)而非栈区,而静态区中存储的内容只会在程序结束时被OS释放,因此当static修饰的局部变量离开自己的作用域时,其不会像一般局部变量那样被系统销毁,而是一直驻留在系统的内存中,直到程序结束。
二、C++中的static
• 静态数据成员:自定义类中被static修饰的成员变量
特别注意:
1.静态数据成员在内存中的存储位置:静态区(全局区)
2.使用:
语法:类名::静态数据成员名
3.静态数据成员属于类。换句话说就是类的静态数据成员为其所有对象所共享,不管该类有多少对象,静态数据成员只有一份存储于公共的内存中
#include<iostream>
#include<string>
using namespace std;
class Student{
public:
static int count;//记录该类的对象的个数
Student(){
count++;
}
Student(string name,int age):Name(name),Age(age){
count++;
}
~Student(){
count--;
}
private:
string Name;
int Age;
};
20 int Student::count=0; //对count进行初始化
int main(){
Student stu1("Tomwenxing",);
Student stu2("Ellen",);
Student stu3("Jack",);
cout<<"Student类的对象的个数:"<<Student::count<<endl;
return ;
}
• 静态成员函数:自定义类中被static修饰的成员函数
特别注意:
1.在C++的自定义类中,一个常规的成员函数声明往往意味着:
• 该成员函数能够访问其所在类的私有部分
• 该成员函数位于其所在类的作用域之中
• 该成员函数必须由一个对象去激活从而被调用(通过this指针来实现)
如果将该类的一个成员函数声明为static,则可以只让它拥有前两种性质
2.使用:
语法1:类名::静态成员函数名
语法2:对象名.静态成员函数名
3.和静态数据成员一样,静态成员函数也属于类,即类的静态成员函数为其所有对象所共享。
4.类中的普通成员函数既可以访问一般成员变量,也可以访问静态数据成员;而类中的静态成员函数只能访问类中的静态数据成员。
[解释]:编译器在编译程序中的自定义类时,会在类中的每个普通成员函数中插入this指针,而对static修饰的静态成员函数则不会插入this指针。由于静态成员函数中没有this指针,因此静态成员函数无法在其函数体内访问非静态数据成员;相反,由于静态数据成员属于类而非特定对象,故不需要this指针也可以在函数体内访问静态数据成员,因此不管是普通成员函数还是静态成员函数,都可以在其函数体内访问静态数据成员。
5.同理,普通成员函数中可以调用静态成员方法,而静态成员方法中不能调用普通成员函数
#include<iostream>
#include<string>
using namespace std;
class Student{
public:
static int count; //静态数据成员
Student(){
count++;
}
Student(string name,int age):Name(name),Age(age){
count++;
}
~Student(){
count--;
}
void show1();
static void show2();
private:
string Name;
int Age; };
int Student::count=0; //对count进行初始化
/*
25 编译器对成员函数show1的改写:
26 void Student::show1(Student* const this){
27 cout<<"Name:"<<this->Name<<endl;
28 cout<<"Age:"<<this->Age<<endl;
29 cout<<"Count:"<<count<<endl;
30 show2();
31 */
void Student::show1(){
cout<<"调用了方法show1"<<endl;
cout<<"Name:"<<Name<<endl;
cout<<"Age:"<<Age<<endl;
cout<<"Count:"<<count<<endl;
show2();//在普通成员函数中调用静态成员函数
}
void Student::show2(){ //编译器不会为静态成员函数添加this指针
cout<<"调用了方法show2"<<endl;
41 //cout<<"Name:"<<Name<<endl; //错误:静态成员函数不能访问非静态数据成员
42 //cout<<"Age:"<<Age<<endl; //错误:静态成员函数不能访问非静态数据成员
43 //show1(); //错误:静态成员函数中不能调用普通成员函数 (只能以this->show1()的形式调用)
cout<<"Count:"<<count<<endl;
}
int main(){
Student stu1("Tomwenxing",);
Student stu2("Ellen",);
Student stu3("Jack",);
stu3.show1();
cout<<"----------分界线----------------"<<endl;
stu2.show2();//可以通过对象来调用静态成员函数
cout<<"----------分界线----------------"<<endl;
Student::show2() ;//也可以通过类来调用静态成员函数
return ;
}
C/C++:static用法总结的更多相关文章
- 从零开始学C++之对象的使用(二):四种对象生存期和作用域、static 用法总结
一.四种对象生存期和作用域 栈对象 隐含调用构造函数(程序中没有显式调用) 堆对象 隐含调用构造函数(程序中没有显式调用),要显式释放 全局对象.静态全局对象 全局对象的构造先于main函数 已初始化 ...
- 四种对象生存期和作用域、static 用法总结
一.四种对象生存期和作用域 栈对象 隐含调用构造函数(程序中没有显式调用) 堆对象 隐含调用构造函数(程序中没有显式调用),要显式释放 全局对象.静态全局对象 全局对象的构造先于main函数 已初始化 ...
- C语言中static用法介绍
C语言中static用法介绍 对于新手来说,很多东西的用法还不是很清楚,我们今天一起来看看C语言中static用法介绍 1.声明了static的变量称为静态变量,根据作用域的不同又分为 ...
- static用法总结
C++的static有两种用法:面向过程程序设计中的static和面向对象程序设计中的static.前者应用于普通变量和函数,不涉及类:后者主要说明static在类中的作用. 一.面向过程设计中的st ...
- c++ static用法总结【转载】
static关键字是C, C++中都存在的关键字.static从字面理解,是“静态的“的 意思,与此相对应的,应该是“动态的“. static的作用主要有以下3个: 1.扩展生存期: 2.限制作用域: ...
- (转-经典-数据段)C++回顾之static用法总结、对象的存储,作用域与生存期
转自:https://blog.csdn.net/ab198604/article/details/19158697相关知识补充:https://www.cnblogs.com/rednodel/p/ ...
- c/c++中static用法总结
static的作用主要有两种: 第一个作用是限定作用域:第二个作用是保持变量内容持久化: c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字static,全局变量就定义成一 ...
- 【C++初级】static用法总结、问题探讨及常见错误排查
static的基本用法: static的作用主要有两种第一个作用是限定作用域:第二个作用是保持变量内容持久化: 一.c语言中static的用法: 1.全局静态变量: 用法:在全局变量前加上关键字sta ...
- java中静态代码块的用法 static用法详解和static静态导入
(一)java 静态代码块 静态方法区别一般情况下,如果有些代码必须在项目启动的时候就执行的时候,需要使用静态代码块,这种代码是主动执行的;需要在项目启动的时候就初始化,在不创建对象的情况下,其他程序 ...
- C/C++ static用法
这篇文章没有太多的实际内容,简单记录下static的用法.顺便试一下用markdown来写文章. 1. 在函数中使用 我们都知道在一个函数中的变量是存储在栈区中,函数的每一次调用都伴随着变量的重新定义 ...
随机推荐
- 解决yum安装 openssl-devel时产生的Multilib version problems found错误(转)
Error: Multilib version problems found. This often means that the root cause is something else and m ...
- 通过ReentrantLock简单了解下并发包中的锁
ReentrantLock在进行实例化时,可以通过构造函数的参数选择是否使用公平锁FairSync或者非公平锁NonfairSync,两者的区别比较简单,如果是公平锁则新来的线程会先检测同步队列中是否 ...
- 郑重推荐开源CANopen协议栈CANFestival(LGPL许可)!!!!!!!!
郑重推荐开源CANopen协议栈CANFestival(LGPL许可)!!!!!!!!(这条文章已经被阅读了 次) 时间:2010/03/04 06:47am 来源:winshton [这个贴子最后由 ...
- vue watch关于对象内的属性监听
vue可以通过watch监听data内数据的变化.通常写法是: data: { a: 100 }, watch: { a(newval, oldVal) { // 做点什么... console.lo ...
- #leetcode刷题之路39-组合总和
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合.candidates 中的数字可以无限制重复被选取 ...
- CO借贷标识及转换
前台提前数据源0CO_PC_01的数据时发现借贷方有O.C.S.D.不是传统的FI借贷标识(S = 借记,H = 贷记). 由"D"指出贷方记帐.从以下项中发生这些记帐 财务会计中 ...
- 说说MySQL索引
前言 关于索引,这是一个非常重要的知识点,同样,在面试的时候也会被经常的问到: 本文描述了索引的结构,介绍了InnoDB的索引方案等知识点,感兴趣的可以看一下: 引入 本文参考文章:MySQL的索引 ...
- C语言的一道数组题Plus
其实数组那部分当时学的东西挺简单的. 常见的题就是用一个数组装几个数字. 然后排序,找出大于n的数字有几个,有几个重复数字之类的. 去年想出来一个题. 因为以前写的代码太复杂,又有很多不足和bug.所 ...
- 在Visual Studio 2012中使用ASP.NET MVC5
去年11月,.NET团队发布了用于 Visual Studio 2012 的 ASP.NET 和 Web 工具 2013.1 您可以从下面提供的链接下载该更新: 下载用于 Visual Studio ...
- P3674 小清新人渣的本愿
P3674 小清新人渣的本愿 一道妙不可言的题啊,,, 一看就知道是个莫队 考虑求答案 1号操作就是个大bitset,动态维护当前的bitset \(S\),把能取哪些值都搞出来,只要\(S\ and ...