1.static关键字
1.1 static全局变量
- 定义:在全局变量前加上关键字static,全局变量就定义成一个全局static变量。内存中的位置:全局存储区(静态存储区),在整个程序运行期间一直存在。
- 初始化:未经初始化的全局static变量会被自动初始化为0。
- 作用域:全局stacit变量在声明他的文件之外是不可见的,准确地说作用于是从定义之处开始,到文件结尾。
- 与全局变量区别:全局static变量在定义该变量的当前源文件内有效,在同一源程序的其它源文件中不能使用它。而普通的全局变量在各个源文件中都是有效的(当一个源程序由多个源文件组成时)。
1.2 static局部变量
- 定义:在局部变量之前加上关键字static,局部变量就成为一个局部static变量。内存中的位置:全局/静态存储区。
- 初始化:未经初始化的static局部变量会被自动初始化为0。
- 作用域:作用域仍为局部作用域,当定义它的函数或者语句块结束的时候,作用域结束。但是当局部static变量离开作用域后,并没有销毁,而是仍然驻留在内存当中,只不过我们不能再对它进行访问,直到该函数再次被调用,并且值不变;
- 与局部变量区别:static局部变量存放在静态存储区,其只在当前函数中起作用,但是其生存周期是直到当前程序结束为止;局部变量存在栈中,声明周期为当前函数。
1.3 static函数
- 定义:在函数返回类型前加static,函数就定义为static函数。函数的定义和声明在默认情况下都是extern的,但static函数只是在声明他的文件只在当前可见,不能被其他文件所用。函数的实现使用static修饰,那么这个函数只可在本文件内使用,不会同其他文件中的同名函数引起冲突。
- 使用规则:一般情况下,在头文件中声明非static全局函数,在cpp内声明static全局函数。因为如果你需要要在多个cpp中使用某个函数,才把该函数的声明提到头文件里去,此时如果声明static全局函数,相当于只在本文件有效,没有达到预期的效果;同理,我们希望cpp文件中static全局函数只在本文件有效,就要设置为static。
- 与普通函数区别:static函数只在当前源文件中起作用,在其他文件中不起作用;普通函数可在其他源文件中调用。static函数与普通函数最主要区别是static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝程序的局部变量存在于堆栈中。
1.4 类的static成员
- 定义:在类中static数据成员可以实现多个对象之间的数据共享,并且使用static数据成员还不会破坏隐藏的原则,即保证了安全性。因此,static数据成员是类的所有对象中共享的成员,而不是某个对象的成员。对多个对象来说,static数据成员只存储一处,供所有对象共用。
- 特性1: static成员变量属于整个类所有,可以通过类名直接访问公有static成员变量(即使stacit数据成员是private),同时也可以通过对象名访问公有static成员变量。
- 特性2:stacit成员变量的生命期不依赖于任何对象,为程序的生命周期。
- 特性3:c++中父类的static成员变量/函数在子类中的使用时,子类是可以共享父类中static成员变量/函数的。当然有一个前提,父类中的静态成员函数/变量应该为public,或者为private时应提供公有的接口来调用。
1.5 类的static数据成员
- 特性1:static数据成员需要在类外单独分配空间(此时称为定义性声明,与类中的引用性声明注意区别,此时static数据成员不占用类的空间),static数据成员在程序内部位于全局静态区。
- 特性2:即使在类中已经声明static数据成员,但是依然需要在类外定义,而且不能重复使用static关键字。因为在类中声明static数据成员,不分配内存。而static变量需要开辟存储空间,所以如果不在类外部开辟空间,则会导致编译错误。
- 特性3:static数据成员的类型可以是const、引用、指针、类类型等等。如果是const,在类外定义的时候const不可省略。
- 特性3补充:通常情况下,类的static成员不能在类的内部初始化。但是我们可以为static成员提供const整数类型的类内初始值,不过要求static成员必须是字面值常量类型的constexpr,初始值必须是常量表达式。因为这些成员本身就是常量表达式,所以它们能用于所有适合于常量表达式的地方。还有,如果某个static成员的应用场景仅仅限于编译器可以替换它的值的情况,则初始化的const或者constexpr static不需要分别定义,否则需要分别定义。
- 特性4:static数据成员可以是不完全类型。特别的,static数据成员的类型可以就是所属的类类型,而非static数据成员则受到限制,只能声明为它所属类的指针或引用。例如:
class Bar{
private:
static Bar mem1;
Bar *mem2;
Bar mem3;
}
- 特性5:static成员可以作为默认实参(因为static成员不属于该类),而普通成员不行。
Class Screen{
public:
Screen &clear(bk=ch);
private:
static const char ch;
}
1.6 类的static函数成员
- 定义:对static成员的访问不需要用对象名。在static成员函数的实现中不能直接引用类中说明的非static成员,可以引用类中说明的static成员。如果static成员函数中要引用非static成员时,必须对象来引用。例如:
Class A{
public:
static void f(A a);
private:
int x;
};
void A::