static关键字的用途总结

要面试了,复习一下c++的语言细节,才发现自己差的还很多。

static int i1=1;
static int i2=1;
int i3;
static int i4;
int main()
{
    static int i5=1;
    int i6=1;
    int i7;
    cout<<&i1<<" "<<i1<<endl;
    cout<<&i2<<" "<<i2<<endl;
    cout<<&i3<<" "<<i3<<endl;
    cout<<&i4<<" "<<i4<<endl;
    cout<<&i5<<" "<<i5<<endl;
    cout<<&i6<<" "<<i6<<endl;
    cout<<&i7<<" "<<i7<<endl;
    getchar();
}

输出:

 

 

 首先说值:

普通/static全局变量(i3)默认初始化为0,普通局部变量初始值未定义(i7)

static局部变量即静态局部变量,也会初始化为0

再说内存存储位置:

先放个进程的内存图:

 

 

其中未初始化+初始化区域就是静态区。注意静态区和常量区还不一样,常量比如:int a=1;的1。或者char* x="123";的“123”。

 

 

 对应这两张图来看就很清晰了

 

 

好,下面进入主题:

全局变量都在静态变量区,不管是不是static

注意未初始化的和未初始化的不在一起的!证据如下,其中第一行的都是带初始化的,第二行不带初始化的,明显可见未初始化的bss段地址比已经初始化的数据段地址更大,更靠上:

 

 

普通局部变量在栈区/堆区,static局部变量在静态变量区。

 

static的不同用法:

1.static全局变量/函数,因为函数肯定是全局的了,所以这俩捏一起说。

只有一个用途:不让其他cpp使用自己,即限制作用域为所在的cpp。如果不带static,其他cpp可以extern修饰进而引用。

所以假设a.cpp里有一个函数f。

如果我们让其他cpp引用这个f函数。那么我们应该把f的声明加入到a.cpp的头文件并且声明时不要加static,这样会导致每个包含a.h的cpp都有一份该函数f的副本,大大增加编译效率!当然这个问题回头另外写一篇博客,就先点到为止。另外永远不要在头文件中定义变量!

如果我们不想让其他cpp引用f函数,则我们直接在f的定义前加上static修饰,这样其他cpp就看不到f函数了(即使包含a头文件的情况下也是看不到的)。

2.static局部变量,如:

void f(){
    static int cnt=0;cnt++;
}

这个函数调用几次,cnt就等于几。

static局部变量和全局变量一起存在静态变量区,二者唯一的区别就是:static局部变量作用域只限于所在的函数,但到达函数以外时并不会释放,而是会保持已有的值继续等待下次调用。

static局部变量只会初始化一次!直到cpp退出才会释放。

3.类中的static成员变量(类的静态成员变量):

static成员变量分配在静态区。

在所有该类的实例(对象)中只存在一个副本,所有对象共享一个该静态变量。

类的静态成员变量需要在类中声明,类外定义,例子如下:

class A{
    static int x;
};
int A::x=1;

 

4.类中的static成员函数:

Static修饰的成员函数,在代码区分配内存。只能调用静态成员变量,别的和普通成员函数区别不大。

概括来说:类的静态成员函数、变量的存储位置不在类里,所以也就理所当然的没有this指针。所以静态成员函数无法调用普通成员变量也就合理了(因为没有this指针,根本找不到相应的变量位置!)。

由于二者都与类绑定,而不与特定对象绑定,所以二者可以除了可以通过对象访问外,还可以通过类名访问(A:: f();)。

另外注意:静态成员函数不能加const限定,可能是因为静态成员函数本身就不会改变类内部数据。

 

posted @ 2020-03-06 13:54  NeoZy  阅读(960)  评论(0编辑  收藏  举报