前言
本次学习C/C++中的static关键字,分别学习C语言和C++语言中的static特点。static是C、C++87中比较重要的一个关键字,它可以用来修饰变量、函数、类成员变量和类成员方法。
一、static变量
在变量声明前面加上static,变量就为静态变量。静态变量的特点:
- 静态变量存储在全局数据区(包括static全局变量和static局部变量)
- 静态变量的生命周期和程序一致,直到程序运行结束,才会释放静态变量占用的内存
1. static全局变量
如果static放在了全局变量声明的前面,那么该变量就为全局静态变量,其特点如下:
- 作用域为整个程序
- 在程序启动时初始化,如果没有显式初始化,则被初始化为0(自动变量初始化是随机的)
//a.cpp
#include <iostream>
static int a = 2233; //static全局变量
int main()
{
a = 2333;
std::cout << a << std::endl;
}
a = 2444; //error:此声明没有存储类或类型说明符
//b.cpp
#include <iostream>
extern int a;
int main()
{
a = 3334;
std::cout << a << std::endl;
}
在编译b.cpp时会报错:
ld: Undefined symbols:
_a, referenced from:
_main in b-9ffdd0.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
2. static局部变量
如果在声明局部变量时加上static关键字,则表明该变量为static局部变量,其特点如下:
- 作用域为当前函数或者语句块
- 第一次调用该static局部变量时会进行初始化,以后调用不再初始化
#include <iostream>
static int a = 2233;
int function(){
static int b = 1;
std::cout << b << "\n";
c = '1';//未定义标志符"c"
}
int main()
{
a = 2333;
b = a;//未定义标志符"b"
static char c = '0';//
std::cout << a << std::endl;
}
二、static函数
在函数的返回值类型前面加上static,即表明该函数为静态函数,其特点:
- 只能在当前文件中被调用,其他文件无法调用该函数
好处在于其他文件可以有重名函数并且不会发生冲突。
#include <iostream>
static void function(){
static int b = 1;
b++;
std::cout << b << "\n";
}
int main()
{
function();//输出:2
function();//输出:3
}
三、类静态成员变量/方法
类的静态成员变量和成员方法是所有类对象共享的,且类的静态成员变量和成员方法不需要实例化类对象也能访问,见代码:
int Player::m_playerCount = 0;
std::cout << "Number of Players: " << Player::GetPlayerCount() << std::endl
#include <iostream>
class Player{
public:
Player(std::string name, int age){
m_name = name;
m_age = age;
m_playerCount++;
}
static int GetPlayerCount() { return m_playerCount; }
void PrintPlayerInfo(){
std::cout << "name: " << this->m_name;
std::cout << ", age: " << this->m_age << std::endl;
}
private:
std::string m_name;
int m_age;
static int m_playerCount;
};
int Player::m_playerCount = 0;
int main()
{
std::cout << "Number of Players: " << Player::GetPlayerCount() << std::endl;//输出:Number of Players: 0
Player p1("Bob", 12);
p1.PrintPlayerInfo();//输出:name: Bob, age: 12
std::cout << "Number of Players: " << p1.GetPlayerCount() << std::endl;//输出:Number of Players: 1
Player p2("Anna", 22);
p2.PrintPlayerInfo();//输出:name: Anna, age: 22
std::cout << "Number of Players: " << p2.GetPlayerCount() << std::endl;//输出:Number of Players: 2
}
1.类静态成员变量
见上述代码中,m_playerCount
为静态成员变量,用来记录玩家数量,在实例化类对象前必须要对该静态成员变量初始化,否则会报错,报错信息如下:
ld: Undefined symbols:
Player::m_playerCount, referenced from:
Player::GetPlayerCount() in a-85fe5c.o
Player::Player(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char>>, int) in a-85fe5c.o
clang: error: linker command failed with exit code 1 (use -v to see invocation)
每实例化一个Player对象时,m_playerCount
都会增加1,同样,每销毁一个Player对象时,m_playerCount
都应该减1(代码中没实现,后续类的介绍中会讲)。
2.类静态成员方法
见上述代码中的GetPlayerCount()
函数,它返回此时的玩家数量。
总结
本次学习了在C/C++中的static关键字,其中在C程序中只会存在static全局(局部)变量和static函数,类静态成员变量和成员方法只有C++中才有,这是C++的面向对象思想的特点。