搜索
热搜: NOIP OIer 神牛
查看: 385|回复: 2

static总结

[复制链接]

35

主题

54

帖子

4532

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
4532
发表于 2023-5-9 10:04:02 | 显示全部楼层 |阅读模式
static 是静态变量的类型说明符.
static修饰局部变量----静态局部变量
static 修饰的局部变量属于静态存储方式.
static修饰局部变量,改变了该变量的生命周期,使该变量的生命周期与程序的生命周期相同,程序结束时才销毁.
以代码为例,体会static修饰局部变量的作用:
#include<iostream>
void A1() {
       static int tmp = 1;
       static int tmp1;
       int ret = 1;
       std::cout <<"tmp:"<< tmp <<'-'<<"ret:"<< ret << std::endl;
       tmp++;
       tmp1++;
       ret++;
}
int main() {
       A1();// 每次调用该函数时, 静态局部还保留着之前的值,说明之初始化了一次
       A1();
       return 0;
}
代码执行结果:
·       0
tmp:1-ret:1
1
tmp:2-ret:1
特点:
static修饰局部变量,改变了该变量的生命周期,它的生命周期与程序的生命周期相同,但是其作用域未改变仍与局部变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
对基本类型的静态局部变量若在声明时未赋以初值,则系统自动赋予0值。而对局部变量不赋初值,则其值是不定的。 根据静态局部变量的特点, 可以 看出它是一种生存期为整个源程序的变量。虽然离开定义它的函数后不能使用,但如再次调用定义它的函数时,它又可继续使用, 而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的,但全局变量有时会造成 意外的副作用,因此仍以采用局部静态变量为宜。
static修饰全局变量----静态全局变量
限定了该变量的作用域,使其只在定义该变量的源文件内有效,非静态全局变量的作用域是定义该变量的整个工程.
static int tmp;
全局变量(外部变量)的说明之前再加上static 就构 成了静态的全局变量。静态全局变量与非静态全局变量在存储方式上都是静态存储方式。这两者的区别虽在于非静态全局变量的作用域是定义该变量的整个工程项目, 当一个工程项目由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的.静态全局变量的作用域是定义该变量的源文件 只在定义该变量的源文件内有效,在同一工程项目的其它源文件中不能使用它.由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此 可以避免在其它源文件中引起错误。从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量 后是改变了它的作用域, 限制了它的使用范围。
static修饰不在类中的函数----静态函数
C语言根据函数能否被其它源文件中的函数调用,将函数分为内部函数和外部函数。
内部函数: 当一个源程序由多个源文件组成时, 如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数称为内部函数。
// static 函数类型 函数名(参数列表)
static void Function(int a, char b,...)
外部函数: 在定义函数时,如果没有加关键字“static”,或加上关键字extern 修饰,表示此函数是外部函数.
外部函数的调用:
// extern 函数类型 函数名 (参数类型表)
extern int Function(int);
静态函数有以下好处:
  <1> 其他文件中可以定义相同名字的函数,不会发生冲突。
  <2> 静态函数不能被其他文件所用。
static修饰类中的函数----静态成员函数
静态成员函数的作用: 调用这个函数不会访问或者修改任何对象(非静态)数据成员。
类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。
注意:
静态数据成员不能在类中初始化,实际上类定义只是在描述对象的蓝图,在其中指定初值是不允许的,但是可以在类定义中可以定义静态的常量数据成员,并且初始化(比如: static const int tt =10 ;)。
如果在类定义中初始化了静态常量数据成员,就不可以在类定义外,初始化该成员了,因为不能初始化多次。
不能在构造函数中初始化常量静态成员数据。因为静态数据成员为类的各个对象共享,否则每次创建一个类的对象则静态数据成员都要被重新初始化。只能在类定义外初始化静态成员数据。 并且只能定义一次。static数据成员在构造函数被调用之前就已经存在了。
静态成员可以是public也可以是private或者是protected,静态数据成员的类型可以是常量、引用、指针、类类型等 。
静态成员函数没有this形参,可以直接访问所属类的static 成员, 但不能直接使用所属类的非static 成员。
静态成员不能声明为const 的。
静态数据成员被 类 的所有对象所共享,包括该类派生类的对象。即派生类对象与基类对象共享基类的静态数据成员。
class Student
{
public:
       static int getCount();
       static int count;
       void outPutAge(int data = age)  定义个成员函数,static数据成员可以作为默认参数
       {
              cout << data << endl;
       }
       void outPutSex(bool s = sex) 错误: 类的普通数据成员不能作为默认参数
       {
       }
       Student myStudent1;  错误,非static数据成员不能定义为所属类的对象
       static Student myStudent2; static 数据成员可以是当前类的类型
  
       Student *myStudent3; 正确, 允许定义类的所属类型的指针类型对象
     static Student &myStudent4();
      
private:
        bool sex;
       static int age;
};
int Student::age = 1;  在类外初始化私有的static数据,要添加 类名::
int Student::getCount()  在类外定义static 函数不需要添加static
{
       return count; 在类的内部使用static 数据成员,不需要使用类名::
}
int main()
{
       Student myStudent;
       Student::count = 1;  利用作用域运算符在类外使用类名初始化公有的static数据
       int temp = Student::getCount(); 调用静态成员函数
       myStudent.count = 2; 使用点运算符还可以使用该类的对象初始化公有的static数据
       Student::age = 2; 错误: 在类外不能初始化 私有static数据
      
       Student *s = &myStudent; 声明一个指针指向该类型对象, 间接调用成员
       s->getCount();  通过指针调用static 成员函数
       s->count; 指针调用公有的static数据成员
       Student &ss = myStudent;
       ss.getCount();
       ss.count;
       system("pause");
       return 0;
}
一个类的静态数据成员仅创建和初始化一次,且在程序开始执行时创建, 然后被该类的所有对象共享。
静态数据成员可以被所有类的对象共享。这就意味着无论定义多少个类对象, 每个类的只有一个静态数据成员的拷贝。

回复

使用道具 举报

主题

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2023-5-14 10:10:21 | 显示全部楼层
回复

使用道具 举报

主题

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2023-5-14 10:10:51 | 显示全部楼层
=( =)
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

津ICP备19006949号-1 | 津公网安备12010102000465号

快速回复 返回顶部 返回列表