Chinaunix首页 | 论坛 | 博客
  • 博客访问: 613896
  • 博文数量: 79
  • 博客积分: 848
  • 博客等级: 军士长
  • 技术积分: 1800
  • 用 户 组: 普通用户
  • 注册时间: 2012-06-26 19:30
文章分类

全部博文(79)

文章存档

2015年(4)

2013年(39)

2012年(36)

分类: C/C++

2013-02-27 16:41:44

最近在读代码的时候遇到了大量的static关键字,自己之前对于static的用法所知的也比较有限,所以就趁着这个机会将c++中static的几种用法做一下简单的总结,希望能够对于大家的学习和使用有一定的帮助作用。

在c++中static一般分为以下几个类别:

(1)静态全局变量

(2)静态局部变量

(3)静态函数

(4)静态成员变量

(5)静态成员函数

本文就按照这样的顺序对于他们的应用场景和作用做一下简单的介绍:

在介绍这些之前我们先来了解一下为什么要引入static?

我们知道在函数内部定义的变量,当程序执行到变量的定义处的时候,编译器在栈区为它开辟出一块内存空间,当程序执行结束的时候销毁这个变量释放这块内存,但是我们在实际的应用场景中会有这样的需求:就是我们在下一次函数调用的时候需要用到某个变量上一次的值。当然,看到这个需求我们一定会想到用一个全局变量不就可以了嘛,但是全局变量有一个比较大问题就是:它不仅仅可以被该函数自己使用,也会暴露给程序中的其他部分,甚至于其他程序文件。这往往不是我们想看到的事情,所以为了解决这个问题c++就引入了static这个关键字,它的目的就是为了解决:当程序块被多次调用时对于某个变量或者是某段代码的共享问题。

在总结之前我们先总体上概括一下程序各个部分在内存中的分布:


代码区:(地址低位)

全局数据区:静态数据成员,全局变量

堆区:程序中动态申请的内存

栈区:(地址高位)局部变量

1、静态全局变量

顾名思义就是在一个全局变量前面加上static修饰符,要了解它的用法我们就要知道它跟全局变量有什么不一样的地方。


比较内容

全局变量

静态全局变量

内存的中的位置

全局数据区

全局数据区

自动初始化操作

自动初始化为零

作用范围

定义该变量的整个程序文件,其他程序文件可以通过extern关键使用。

仅限于定义该变量的程序文件自己使用,其他文件不可使用。

通过这样一个简单的比较我们就了解静态全局变量相比于一般的全局变量而言在变量的作用区间上有了更加严格的限制,这样在特定的条件下将更有利于程序的安全性。

2、静态局部变量

同理就是加上了static修饰符的局部变量,所谓局部变量就是在某个函数内部定义的变量。我们还是按照同样的方法进行分析。


比较内容

局部变量

静态局部变量

内存的中的位置

栈区

全局数据区

初始化操作

程序执行到函数体内该变量的定义处执行初始化操作。

程序执行到函数体内该变量的声明处执行初始化操作,如果没有初始化操作会自动初始化为0。如果在程序中该函数被多次调用,静态变量不会被重新初始化,也就是说它会保留上次的赋值,直到新的赋值语句将其覆盖。也就是说程序不会为静态变量重新分配内存空间。

作用范围

定义该变量的函数体内。

定义该变量的函数体内

生命周期

定义该变量的函数执行结束,变量销毁。

整个程序文件执行的过程中一直存在,直到程序执行结束。

通过比较我们知道,静态局部变量就能够很好的解决我们之前提到的那个应用场景中的问题。

3、静态函数

所谓的静态函数就是在函数的返回类型之前加上static关键字,跟一般的函数不同,静态函数仅仅能够在声明该函数的文件中使用,对于其他文件不可见,也就是说在其他的文件中可以不会发生命名冲突的情况。

4、静态成员变量

假如我们在一个类的成员变量前面加上static关键字就变成一个静态的成员变量,相比于一般的成员变量它有什么特点呢。


比较内容

成员变量

静态成员变量

内存的中的位置

栈区

全局数据区

初始化操作

在类的构造函数之中将其初始化。

不能在构造函数中将其初始化,因为它隶属于这个类,而不是从属于类的某个具体的对象,所以不能够在构造某个对象时将其初始化,而必须在类定义的时候按照成员函数一样将其初始化。

类型 类名::变量名 = xxx

作用范围

某个具体的对象,如果该类有多个对象,对于一般的成员变量,在每个对象中都会有一份拷贝,占据一块内存。

定义该静态函数的这个类,也就是说一旦该类定义了静态成员变量,即便没有实例化也可使用该成员变量,假如实例化了多个对象它在内存中也仅存有一份,为所有该类的对象共享。

类名::变量名

当然也可用访问一般成员变量的方式来访问。

生命周期

依存于某个具体的对象,一旦对象销毁,该变量即销毁。

依存于这个类,只要类存在静态变量就存在。

通过比较我们可以看出,这种静态数据成员已经部分具有了全局变量的功能,同时将这个变量的作用域可以用类的public、protected、private来加以限制,从而加强了变量的封装进而增加了程序的安全性。而且可以实现面向对象的资源共享功能,将大家共有的成员变量,定义为静态数据成员。

5、静态成员函数

与静态数据成员一样,我们也可以创建一个函数,它为类的全部服务而不是为某一个类的具体对象服务。函数与静态数据成员一样,都是类的内部实现,属于类定义的一部分。普通的成员函数一般都隐含了一个this,this指针指向类的对象本身,因为普通成员函数总是具体的属于某个类的具体对象的。通常情况下,this 是缺省的。如函数fn()实际上是this->fn()。但是与普通函数相比,数由于不是与任何的对象相联系,因此它不具有this指 针。从这个意义上讲,它无法访问属于类对象的非静态数据成员,也无法访问非函数,它只能调用其余的静态成员函数。

它的这些特性有什么作用呢,显然我们可以将对整个类的静态成员变量的操作交给静态成员函数来完成。

阅读(2237) | 评论(2) | 转发(1) |
给主人留下些什么吧!~~

风箫夜吟2013-03-03 16:04:54

Bean_lee:在确定不会被其他文件调用的函数,最好定义为static,最少暴露原则,动态库尤其如此。
Ulrich Drepper曾有文章提到过这个。

有理,感觉自己读的书还是太少了……

回复 | 举报

Bean_lee2013-03-02 23:19:49

在确定不会被其他文件调用的函数,最好定义为static,最少暴露原则,动态库尤其如此。
Ulrich Drepper曾有文章提到过这个。