最近经常碰到static,之前也使用过,但都是一知半解,所以下决心做个整理总结,搞搞灵清它到底用哪些作用。
一.static in C
1.默认初始化为0:
如果不显式地对静态变量进行初始化,它们将被初始化为0。
static变量存放在Global/Static(全局区/静态区)。在静态数据区,内存中所有的字节默认值都是0x00,所以在程序一开始时static声明的变量会被默认初始化为0。
2.static声明的变量会一直保持其值(局部静态对象)
static变量存放在Global/Static(全局区/静态区)。程序一开始,对其进行唯一一次初始化。被函数调用后,static变量不会消失,计算机会一直记录其值,其生命周期是贯穿函数调用及之后的时间。
#include <stdio.h>
void funcion(); int main()
{
for(int count = ; count <= ; count++) {
printf("第%d次调用:",count);
funcion();
} //for循环中的count内存被释放
return ;
} void funcion()
{
int temp = ;
static int count = ;//只在函数第一次调用时执行,后续函数调用此变量的初始值为上次调用后的值,每次调用后存储空间不释放
printf("temp = %d static count = %d\n",temp--, count--);
}
Eg Code
static count每次调用,其值减1,而temp每次都重新开始都为10。而主函数for循环中的count是在栈区的,作用域只在主函数的for循环中,当循环结束是存储空间自动释放。
3.具有内部链接的静态变量(static variable with internal linkage)
普通的外部变量可以被程序的任一文件所包含的函数使用,而具有内部链接的静态变量只可以被与它在同一个文件中的函数使用。
//举个例子
文件1:a.c
int money = ;
static wife = ;
int main()
{
money++;
printf("wife = %d\n",wife);
}
void function()
{
money--;
printf("wife = %d\n",wife);
}
文件2:b.c
int main()
{
extern int money;
money--;
printf("money = %d\n",money);
return ;
}
a.c中main函数,function函数皆可调用money和wife。b.c用外部声明extern money,是可以输出money = 9的。但是不能extern int wife,因为在a.c 中wife 加了static,其只允许在a.c中使用。(就像好兄弟money是可以共享的,但是wife不行!)
在多文件构成的程序中,如需共享一个外部变量,除了一个声明(定义声明)外,其他所有声明都要加extern;而如果不想被共享的变量,那就在声明时用static,表明该变量具有内部链接。
二.static in C++
1.静态数据成员
#include <iostream>
#include <string>
using namespace std; class Account
{
public:
static int sumAccount; //声明静态数据成员
void calculate() {
amount += amount * interestRate;
}
static double rate() {
return interestRate;
}
static double rate2(double interestRate2 = interestRate) {//使用静态成员作为默认实参。
return interestRate2;
}
// [Error] invalid use of non-static data member 'Account::amount'普通数据成员值不能作为默认实参
// static double showAmount(double Amount = amount) {
// return Amount;
// }
static void rate(double);
private:
string owner;
double amount;
static double interestRate; //声明静态数据成员
static double initRate();
};
double Account::interestRate = 0.30;//定义并初始化静态数据成员
int Account::sumAccount = ; //定义并初始化静态数据成员 int main()
{
Account ac1;
Account *ac2 = &ac1;
Account &ac3 = ac1;
cout << ac1.sumAccount << endl;
cout << ac2->sumAccount << endl;
cout << ac3.sumAccount << endl;
cout << Account::sumAccount << endl;
return ;
}
Eg Account Code
1.静态成员存在于任何对象之外,对象中不包含任何与静态数据成员有关的数据。静态数据成员只分配一次内存,即只存在一个static成员对象,被该类所有的对象共享。
Eg:每个Account对象都包含数据成员owner和amount。只存在一个interestRate对象被所有Account对象共享。
2.静态数据成员存放在Global/Static(全局区/静态区)。不是由类的构造函数初始化的。必须在类的外部定义和初始化每个静态数据成员,且只能定义一次。一旦被定义,就将存在于程序的整个生命周期。在外部定义静态数据成员时,不能重复static关键字。
Eg:静态数据成员的定义 double Account::interestRate = 0.30;
3.静态数据成员遵守public/protected/private访问规则。
4.静态数据成员的访问: (静态数据成员为public)
①作用域运算符直接访问静态数据成员
Eg: <类类型名>::<静态数据成员名>
Account::sumAccount;
②仍可以用类的对象,引用或者指针来访问静态数据成员。
Eg: <类对象名>.<静态数据成员名>
ac1.sumAccount;
5. 静态数据成员与普通成员区别:
①静态数据成员可以是不完全类型。指针成员可以是不完全类型。数据成员必须是完全类型。
②可以使用静态成员作为默认实参。普通数据成员值本身属于对象的一部分。(Eg:代码中被注释段)
③由于被该类所有的对象共享,改变其值,对于所有对象都改变了,无需逐一改变。
6. 静态数据成员与全局变量的区别:
①静态数据成员在类内,作用域与全局变量不同。且实现了封装性。
②静态数据成员可以实现信息隐藏,可以是private。而全局变量不能。
2.静态成员函数
#include <iostream>
#include <string>
using namespace std; class Account
{
public:
void calculate() {
amount += amount * interestRate;//非静态成员函数可以访问静态数据成员
}
static double rate() {
return interestRate; //静态成员之间可以相互访问
}
static void rate(double);
private:
string owner;
double amount;
static double interestRate;
static double initRate();
};
double Account::interestRate = 0.30; void Account::rate(double newRate) { //定义静态成员函数,不能重复static关键字
interestRate = newRate;
} int main()
{
Account ac1;
Account *ac2 = &ac1;
Account &ac3 = ac1;
cout << ac1.rate() << endl;
cout << ac2->rate() << endl;
cout << ac3.rate() << endl;
Account::rate(0.35);
cout << Account::rate() << endl;
return ;
}
Eg2 Account Code
1.静态成员函数不与任何对象绑定在一起,被所有Account对象共享。它们不包含this指针。静态成员函数不能声明称const的,且不能再static函数体内使用this指针。
2.静态成员函数,既可以定义在类内,也可以定义在类外部。(通常情况,类的静态成员应该在类的外部初始化。)在外部定义静态成员时,不能重复static关键字,只能出现在类的内部声明。
Eg:Eg2 Account Code 行23-25
3.静态成员之间可以相互访问,包括静态成员函数访问静态数据成员和访问静态成员函数
4.成员函数不用通过作用域运算符就直接使用静态函数。
5.静态成员函数的访问: (静态成员函数为public)
①作用域运算符直接访问静态成员函数
Eg: <类类型名>::<静态成员函数名>
Account::rate();
Account::rate(0.35);
②仍可以用类的对象,引用或者指针来访问静态成员函数。
Eg: <类对象名>.<静态成员函数名>
ac1.rate();