浅谈C/C++中的static关键字

缘由:因为最近在刷笔试题的过程中,很高频率都出现了关于static关键字的考察,因此在查阅资料加上自己理解的情况下,特整理如下:
参考了大佬的整理,在此感谢!https://www.cnblogs.com/qintangtao/p/3285937.html

首先,在c的面向过程和c++的面向对象两种思路下,就形成了静态的变量或函数和静态的对象以及类
其次要知道的一点是:对于一个完整的程序,在内存中的分布情况如下图:

一般在程序中new生成的动态数据存放在堆区,函数内部的自动变量存放在栈区。自动变量会随函数生命周期的结束而被释放。而静态数据(包括在函数内部声明的静态局部变量),都存放在全局数据区。不会因为函数生命周期的结束而被释放

根据static关键字所在位置进行划分

面向过程中的static

1、在全局变量前加static关键字,就形成了静态全局变量
静态全局变量和普通变量相比具有以下特点:

  • 该变量在全局数据区分配内存;
  • 未经初始化的静态全局变量会被程序自动初始化为0(自动变量的值是随机的,除非它被显式初始化);
  • 静态全局变量在声明它的整个文件都是可见的,而在文件之外是不可见的(影藏性);
  • 当前文件定义静态全局变量后,其他文件定义相同名字的变量将不会产生冲突。

2、在函数内部变量前加上static关键字,就形成了静态局部变量。静态局部变量具有以下特点:

  • 在全局数据区为变量分配内存;
  • 变量在程序执行到该对象声明处时首次初始化,之后函数再次调用不在进行初始化;
  • 如果没有初始化,静态局部变量将被自动初始化为0;
  • 变量存在于全局数据区,函数生命周期结束时,变量的作用域结束,但是变量依然存在,直到当前文件完全结束退出。

静态局部变量存在的意义(为什么需要定义一个变量为静态局部变量?)
在函数内部定义一个普通局部变量,每当调用该函数时,都会给局部变量在栈中分配内存,随着函数调用结束,栈内存也被回收, 变量就随之失效了。 基于这种属性,如果我们需要一个变量再次调用的时候依然沿用之前保持下来的值。只有两种实现方式:定义一个全局变量;定义一个镜头局部变量。
分别说一下:
全局变量,并不属于函数,对于后期代码的维护是不方便的,因此不建议。
静态局部变量,首先是属于函数的,而且仅仅初始化一次,因此可以实现二次调用时候依然保持上一次的值。

3、静态函数:在函数名前加上static关键字就形成了静态函数。具有以下特点:

  • 静态函数不能够被其他文件引用;
  • 在其他文件中可以定义相同名字的函数,不会引起冲突。

面向对象中的static

1、静态数据成员:在类中的对象成员前加static关键字就形成了静态数据成员。与非静态数据成员相比较具有以下特点:

#include<iostream>
using namespace std;

class Myclass
{
private:
    int a , b , c;
    static int sum;  //声明静态数据成员
public:
    Myclass(int a , int b , int c);
    void GetSum();
};

int Myclass::sum = 0;   //静态数据成员存储在全局数据区。静态数据成员定义时要分配空间,所以不能在类声明中定义。

Myclass::Myclass(int a , int b , int c)
{
    this->a = a;
    this->b = b;
    this->c = c;
    sum += a+b+c;
}
void Myclass::GetSum()
{
    cout<<"sum="<<sum<<endl;
}

int main(void)
{
    Myclass M(1 , 2 , 3);
    M.GetSum();
    Myclass N(4 , 5 , 6);
    N.GetSum();
    M.GetSum();
    return 0;
}

关注代码中 int Myclass::sum = 0; 注释

  • 对于非静态的数据成员,每当创建了一个类对象就会有一份数据成员的拷贝;但是对于静态数据成员,无论定义了多少个类的对象,只有一份拷贝。
  • 静态数据成员是所有对象所共有的,对于多个对象来说,静态数据成员只分配一次内存,供所有共用;
  • 和普通成员对象一样遵从public、private、protected访问规则;
  • 因为静态数据成员在全局数据区分配内存,属于本类的所有对象共享,所以,它不属于特定的类对象,在没有产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。比如可以通过<类对象名>.<静态数据成员名>去调用它或者<类类型名>::<静态数据成员名>;
  • 静态数据成员主要用在各个对象都有相同的某项属性的时候。比如定义一个people类,对于不同类型的人,都有的相同属性姓名、身高、体重等属性就可以定义为静态成员变量;

2、静态成员函数:在类中的函数名前加static关键字就形成了静态成员函数。与普通成员函数相比较具有以下特点:

  • 类的静态成员函数为类的全部服务而不是为类中的某一个具体对象服务(如定义成员变量后,用于数据写入的setName()函数就是为某一个具体对象服务的);
  • 普通成员函数都有一个隐含的this指针,用于指向类对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,静态成员函数由于不是与任何的对象相联系,因此它不具有this指针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非静态成员函数,它只能调用其余的静态成员函数。

静态成员函数特点总结:

  • 静态成员函数不能访问非静态成员函数和非静态数据成员;
  • 出现在类体外的函数定义不能指定关键字static;
  • 静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数;
  • 非静态成员函数可以任意地访问静态成员函数和静态数据成员;
  • 由于没有this指针的额外开销,因此静态成员函数与类的全局函数相比速度上会有少许的增长;

以上

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值