C++学习笔记——static关键字

来源:互联网 发布:贵州省网络测评中心 编辑:程序博客网 时间:2024/06/05 21:51

面阿里的时候被问了这个关键字的用法,问题很简单,但是当时答得一般,故总结一番。

首先说static,表示静态,这是一个C语言里面就有的关键字,C++中仍旧沿用并做了些许扩展。

在解释static关键字之前,先了解一下程序的内存布局。

内存布局

一个程序本质上包含bss段、data段和text段。
bss段通常存放程序中未初始化的变量,如全局变量和静态变量,在编译器编译时分配,系统释放;
data段则用来存放程序中已经初始化的变量,包括堆(heap)、栈(stack),以及一些全局变量、静态变量和常量。
而text段则用来存放程序执行的代码,并且通常为只读的。

堆和栈

给一个列表对比两者区别吧。

名称 堆 栈 申请方式 程序员动态申请 系统自动分配 释放方式 程序员释放,否则由OS回收 系统自动释放 系统响应 遍历一个记录空闲地址的链表,返回堆节点 栈空间足够大时提供内存,否则报栈溢出 大小限制 较大较灵活(有效的虚拟内存都可以) 较小而且受限(栈空间大小固定) 申请效率 相对较慢 速度快 存储内容 程序员自行安排 下一条指令地址>参数>局部变量 扩展结构 高地址扩展结构 低地址扩展结构,由专门的指令完成压栈出栈

继续说static关键字,它到底可以修饰什么,有什么作用呢?

全局变量

用static修饰全局变量,该变量就成为一个静态全局变量。

#include<iostream>  using namespace std;  int m;      //定义全局变量 static int n;  //定义静态全局变量int main(void)  {      n = 20;     m = 30;     cout<<n<<" "<<m<<endl;      return 0;  }  

m被定义为全局变量,n为静态全局变量,它们都是在全局数据区分配内存,但是全局变量是整个程序可见的,而静态全局变量则仅在声明它的文件可见,在文件之外是不可见 。定义全局变量可以实现变量在所有源文件之间的共享,而定义静态全局变量,一方面可以隐藏该变量,另一方面其他文件中也可以出现同名定义而不会导致冲突。
总之,static修饰全局变量,改变了这个变量的作用域

局部变量

用static修饰局部变量,该变量就成为一个静态局部变量。
通常函数体内定义的一个局部变量,每当程序运行到变量定义语时,才会为该局部变量分配栈空间,随着程序退出函数体,系统会回收栈内存,局部变量也相应被释放。而静态局部变量同静态全局变量一样,存放于全局数据区,只被初始化一次,而且全局数据区的数据不会因为函数退出而释放空间,也即下一次调用时变量的值不会被重置。
总结,static修饰局部变量,改变了这个变量的内存存储位置,并且改变了它的生命周期

函数

用static修饰函数,该函数则被定义为静态函数。
静态函数同静态全局变量一样,只在声明它的文件中可见,而不能被其它文件使用。
static修饰函数,改变了这个函数的作用域

类成员变量

用static修饰类的成员变量,这个变量就是类内的静态数据成员。
对于非静态数据成员,每个类对象都会有一份拷贝,而静态数据成员则为该类的所有实例共享,无论定义了多少个类对象,静态数据成员在程序中只有一份拷贝,由所有对象共享访问。静态数据成员存储在全局数据区,只分配一次,供所有对象公用。
注意:
1、静态数据成员为该类的所有实例共享,任何类实例修改了该变量,对其他实例均可见;
2、静态数据成员定义时需要分配空间,因此不能在类声明时定义;
3、静态数据成员和普通成员一样遵循public、protected、private访问规则。
总结,static修饰类成员变量,节省存储空间,并且由所有对象共享

类成员函数

用static修饰类的成员函数,这个函数就是类内的静态成员函数。
普通类成员函数一般都隐含了一个this指针,指向类对象本身。而类的静态成员函数与静态数据成员一样,为整个类所有,因此它没有this指针,因此它也无法访问非静态数据成员或非静态成员函数
注意:
1、非静态成员可以访问静态成员,但是静态成员只能访问静态成员。
2、静态成员函数没有this指针的开销,相比类全局函数速度上会稍快。