分类: C/C++
2011-02-24 23:48:52
static最基本含义是指“位置不变的某个东西”,这里指内存中的物理位置或文件的可见性。
1,C++从C继承来的2种基本含义:
a,在固定地址上分配,也就是说对象是在一个特殊的静态数据区上创建的,而不是每次函数调用时在堆栈上产生的。
b,对一个特定编译单元来说是本地的。static控制名字的可见性,这个名字在这个编译单元或类之外是不可见的。
2,函数内部的静态变量
函数体内定义普通变量时,编译器使得每次函数调用时堆栈的指针都向下移一个适当的位置,为这些变量在堆栈中分配内存。
有时想在两次函数调用之间保留一个变量的值,可以通过定义一个全局变量来实现,但这样,这个全局变量不仅仅受这个函数的控制的。
函数内部创建static局部变量,这个变量存储在程序的全局静态数据区中,而不是在堆栈中。
static char* s;
没有为一个预定义类型的静态变量提供一个初始值的话,编译器也会在程序开始时初始化其值为0。
2,函数体内部的静态对象
编译器自动初始化为0只对预定义类型有效,用户自定义类型必须用构造函数来初始化。
3,静态对象的析构函数
静态对象的析构函数在程序从main退出时,或者C标准库函数exit被调用时才被调用。析构函数调用exit是危险的,会陷入死循环。
静态对象的销毁按它们初始化相反顺序进行。编程系统会记录对象初始化的顺序和那些已经被创建的对象。
如果一个包含静态对象的函数从未被调用,则那个静态对象的构造函数不会被执行。
全局静态对象的构造函数在main之前调用的,并且可以在退出main之后用析构函数执行代码。
4,改变变量可见性,所有编译单元可见改变为当前编译单元可见,外部连接改变为内部连接
文件范围内的所有普通对象或函数,对程序中的所有编译单元都是可见的,即外部连接。
文件范围内,声明static的对象或函数对编译单元来说是局部变量,是内部连接。
连接只引用那些在连接/装载期间有地址的成员,因此类声明和局部变量并没有连接。
文件范围内定义:
int a=0;
:::a存储在程序静态数据区,进入main之前已经被初始化。a全局可见,即对所有编译单元可见。
可见性方面static的反义是extern,上面的定义和下面的定义相同
extern int a=0;//a是一个外部连接,所有编译单元可见
static int a=0;//a是一个内部连接,编译单元内可见。
全局变量使用static,存储类型未变,都是静态数据区。static使变量由外部连接改变为内部连接
局部变量使用static,可见性未变,都是内部连接。static使变量存储类型由堆栈改变为静态数据区
函数名使用static,改变可见性
extern void f();//
void f();//可见性同上
static void f();//编译单元内可见。也称为文件静态。
5,名字空间
全局函数、全局变量以及类的名字是在同一个名字空间中。
a,namespace只能在全局范畴定义,可以互相嵌套
b,定义结尾,右大括号后面不必跟一个分号
c,一个namespace可以在多个头文件中用一个标识符来定义
d,未命名名字空间,每个编译单元只有一个未命名名字空间。一个局部名字放在未命名名字空间中,无需加static说明就可以作为内部连接。
f,一个名字空间的类定义之内插入一个friend声明,则它成为名字空间的一个成员。
namespace me{
class us{
friend you();//you()成为名字空间me的一个成员
};
}
6,使用名字空间
2种使用方法:a,范围分解运算符;b,using指令;c,using声明
namespace U{
void f();
}
namespace V{
void f();
}
void func(){
using namespace V;//using directive using指令
using U::f;//using declaration using声明
f();//calls U::f()
V::f();//必须使用全称
}
7,类的静态数据成员-所有类公有的数据成员
类的静态数据成员。拥有一块单独的存储区,所有类对象实例的共享这块静态存储空间,为这些对象实例提供了互相通信的方法。
定义必须出现在类的外部而且只能定义一次,因此它通常放在一个类的实现文件中。
class A{
static int i;
public:
}
定义文件中,
int A::i=1;//定义类静态数据成员,这里类名和范围分解运算符用于指定i的范围。
而定义普通全局变量为
int i=1;
8,类的编译时常量
const static常量,即是常量(不会改变)又是静态的(整个类只有唯一一个定义点)。
和全局常量一样,并不会为常量分配存储空间。
9,静态成员函数-所有类公有的成员函数
像静态数据成员一样,也可创建静态成员函数,为类的全体服务而不是为一个类的部分对象服务。这样就不用定义一个全局函数。
静态成员函数不能访问一般数据成员,只能访问静态数据成员,也只能调用其他的静态成员函数。静态成员函数没有this指针。
10,存在依赖关系的静态数据成员初始化
静态对象的初始化顺序严格按照对象在该单元中定义出现的顺序。
存在依赖关系的静态成员初始化易引起问题。
3种方法解决方法:
a,不用它,避免初始化时互相依赖
b,把关键的静态对象定义放在一个文件中,按在文件中的顺序初始化
c,
11,转换连接指定
C++中用到C库,使用 extern "C"
extern "C" float f(int a,char b);
其它文章:
1,C++中的static关键字 http://www.vckbase.com/document/viewdoc/?id=1720
2,C/C++中的静态作用详述 http://developer.51cto.com/art/200812/103804.htm