每日一面——static关键字

写前声明:参考链接 C++面经面试宝典

✊✊✊每日一面——static关键字

    • 一、全局变量和static变量的异同
    • 二、普通函数和static函数的区别
    • 三、静态成员与普通成员的区别
    • 四、static的作用
    • 五、C++中的类成员声明static
    • 六、静态变量什么时候初始化?

一、全局变量和static变量的异同

  • 存储方式: 全局变量和静态变量都是静态存储方式
  • 作用域: 非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的,而静态全局变量则被限制了其作用域,只能用于被自己定义时的一个源文件内,可以避免在其他源文件中引起的错误
  • 初始化: static全局变量只能初始化一次,防止在其他文件单元被引用

二、普通函数和static函数的区别

  • static函数与普通函数的函数作用域不同,即在当前源文件中使用的函数应该声明为内部函数(static),内部函数应该在当前源文件中声明和定义
  • 对于可在当前文件以外使用的函数应该在一个头文件中声明,要使用这些函数的源文件需要包含这个头文件

三、静态成员与普通成员的区别

  • 生命周期
    • 静态成员变量从类被加载开始直到类被卸载,一直存在
    • 普通成员变量只有在类创建对象后才存在,对象结束时它的生命周期也跟着结束
  • 共享方式: 普通成员变量存储在栈或堆中,而静态成员变量存储在静态全局区(.data / .bss)中,被类的所以对象共享,包括派生类的对象
  • 初始化方式: 普通成员变量在类中初始化,静态成员变量在类外初始化,且不要出现static关键字和private、public、protected访问规则
  • 默认实参: 静态成员变量可以作为成员函数的参数
  • 类型: 普通数据成员的类型只能说该类类型的指针或引用,而静态数据成员可以说所属类的类型

四、static的作用

  • 隐藏: 当同时编译多个文件时,所以未加static前缀的全局变量和函数都有全局可见性,静态函数只能在本源文件中使用
  • 持久: static 作用于局部变量,改变了局部变量的生存周期,使得该变量存在于定义后直到程序运行结束的这段时间
  • static 作用于类的成员变量和类的成员函数,使得类变量或者类成员函数和类有关,即不定义类的对象就可以通过类访问这些静态成员。(注意:类的静态成员函数中只能访问静态成员变量或者静态成员函数,不能将静态成员函数定义成虚函数。

五、C++中的类成员声明static

① 函数体内static变量的作用范围为该函数体,不同于auto变量,该变量的内存只被分配一次,因此其值在下次调用时仍维持上次的值;

② 在模块内的static全局变量可以被模块内所有函数访问,但不能被模块外其它函数访问;

③ 在模块内的static函数只可被这一模块内的其它函数调用,这个函数的使用范围被限制在声明它的模块内;

④ 在类中的static成员变量属于整个类所拥有,对类的所有对象只有一份拷贝;

⑤ 在类中的static成员函数属于整个类所拥有,这个函数不接收this指针,因而只能访问类的static成员变量。

⑥ static类对象必须要在类外进行初始化,static修饰的变量先于对象存在,所以static修饰的变量要在类外初始化;

⑦ 由于static修饰的类成员属于类,不属于对象,因此static类成员函数是没有this指针的,this指针是指向本对象的指针。正因为没有this指针,所以static类成员函数不能访问非static的类成员,只能访问 static修饰的类成员;

⑧ static成员函数不能被virtual修饰,static成员不属于任何对象或实例,所以加上virtual没有任何实际意义;静态成员函数没有this指针,虚函数的实现是为每一个对象分配一个vptr指针,而vptr是通过this指针调用的,所以不能为virtual;虚函数的调用关系,this->vptr->ctable->virtual function

六、静态变量什么时候初始化?

  • 初始化只有一次,但是可以多次赋值,在主程序之前,编译器已经为其分配好了内存。 静态局部变量和全局变量一样,数据都存放在全局区域,所以在主程序之前,编译器已经为其分配好了内存但在C和C++中静态局部变量的初始化节点又有点不太一样。

  • 在C中,初始化发生在代码执行之前,编译阶段分配好内存之后,就会进行初始化,所以我们看到在C语言中无法使用变量对静态局部变量进行初始化,在程序运行结束,变量所处的全局内存会被全部回收。

  • 而在C++中,初始化时在执行相关代码时才会进行初始化,主要是由于C++引入对象后,要进行初始化必须执行相应构造函数和析构函数,在构造函数或析构函数中经常会需要进行某些程序中需要进行的特定操作,并非简单地分配内存。所以C++标准定为全局或静态对象是有首次用到时才会进行构造,并通过atexit()来管理。在程序结束,按照构造顺序反方向进行逐个析构。所以在C++中是可以使用变量对静态局部变量进行初始化的。

📣📣📣重点来了!!!

  • 当调用一个对象的非静态成员函数时,系统会把该对象的起始地址赋给成员函数的this指针。而静态成员函数不属于任何一个对象,因此C++规定静态成员函数没有this指针。既然它没有指向某一对象,也就无法对一个对象中的非静态成员进行访问。同样,没有this指针,无法通过vptr找到vtable,因此它也无法被声明为虚函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

leisure-pp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值