static 是 C++ 中常用的关键字,被 static 修饰的变量只会在 静态存储区(常量数据也存放在这里) 被分配一次内存,生命周期与整个程序一样,随着程序的消亡而消亡。
1. 在文件中定义的 静态全局变量
2. 在函数中定义的静态变量
3. 类的静态成员变量
4. 静态类对象
5. 类的静态方法
- // main.cpp
- #include
-
- int xxx = 66;
-
- static int yyy = 888;
-
- int main()
- {
- std::cout << xxx << std::endl;
- std::cout << xxx << std::endl;
-
- return ;
- }
全局变量默认是有外部链接性的,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过 extern 全局变量名的声明,就可以使用全局变量。
全局静态变量是显式用 static 修饰的全局变量,作用域是声明此变量所在的文件,其他的文件即使用 extern 声明也不能使用。
在函数中定义的静态变量仅仅初始化一次,且变量会存储到静态存储区,因此即便离开函数作用域也不会消失。
- // c.h
- #include
- #include
-
- class C
- {
- public:
- C(std::string n):name(n)
- {
- std::cout << "constructor C " << std::endl;
- }
- ~C(){
- std::cout << "destructor C " << std::endl;
- }
-
- std::string getName()
- {
- return this->name;
- }
-
- private:
- std::string name;
- };
-
-
- // main.cpp
-
- #include
- #include"c.h"
-
- void testStatic()
- {
- static int count = 0; // 只会被初始化一次
- cout << "count: " << count++ << endl; // 每次调用该函数都会将上次存储的值打印出来
- }
-
- C& getTestStaticC()
- {
- static C c("I'm static object."); // 只初始化一次,生命周期与程序等长
-
- return c;
- }
-
-
- int main()
- {
-
- testStatic();
- testStatic();
- testStatic();
-
- C& cc1 = getTestStaticC(); // 因为定义的静态变量存储在静态存储区,不是在栈上,因此离开函数作用域以后,对静态的引用仍然是可以访问的
- C& cc2 = getTestStaticC(); // 因为定义的静态变量存储在静态存储区,不是在栈上,因此离开函数作用域以后,对静态的引用仍然是可以访问的
-
- std::cout << "cc1: " << cc1.getName() << std::endl;
- std::cout << "cc2: " << cc2.getName() << std::endl;
- C cc3("666888");
-
- return 0;
- }
-
-
输出:

类的静态成员变量属于类的所有对象,其存储在静态存储区,只有一个存储空间;而其他的非静态变量属于每个对象,在每个对象中都有其副本。
静态成员变量不在构造函数中初始化,因此静态成员变量不依赖于对象。
静态成员变量必须显示的初始化,一般情况下,我们都在类的外部对静态成员变量初始化,若是静态成员变量未被初始化,编译链接时,会报错。
- // c.h
- #include
- #include
-
- class C
- {
- public:
- C(std::string n):name(n)
- {
- std::cout << "constructor C name: " << this->name << std::endl;
- }
- ~C(){
- std::cout << "destructor C name: " << this->name << std::endl;
- }
-
- std::string getName()
- {
- return this->name;
- }
-
-
- private:
- public:
- std::string name;
- static int height;
- };
-
-
- // c.cpp
- #include "c.h"
-
- int C::height = 66; // 静态成员变量需要显示的定义在类的外部
-
-
- // main.cpp
- #include"c.h"
- #include
-
- int& testStatic21()
- {
- C c("static21 test");
- std::cout << "name: " << c.getName() << " , height: " << c.height << std::endl;
-
- return c.height;
- }
- std::string& testStatic22()
- {
- C c("static22 test");
- std::cout << "name: " << c.getName() << " , height: " << c.height << std::endl;
-
- return c.name;
- }
-
- int main()
- {
- int& abc = testStatic21();
-
- std::cout << "abc: " << abc << std::endl; // 因为存储在静态存储区,所以离开函数作用域后,变量仍然存在
-
- std::string& name = testStatic22();
- std::cout << "name: " << name << std::endl; // 非静态成员变量实际存储位置是函数的栈空间中,因此离开函数作用域后,就会被释放掉,所以获取结果未可知
-
- return 0;
- }
-
输出:

static 关键字对类对象的工作方式也相同。声明为 static 的对象将分配到静态存储区中,并且一直作用到程序结束。
注:使用
static关键字分配为零仅适用于原始数据类型,不适用于用户定义的数据类型。
- // c.h
- #include
- #include
-
- class C
- {
- public:
- C(std::string n):name(n)
- {
- std::cout << "constructor C name: " << this->name << std::endl;
- }
- ~C(){
- std::cout << "destructor C name: " << this->name << std::endl;
- }
-
- std::string getName()
- {
- return this->name;
- }
-
-
- private:
- public:
- std::string name;
- };
-
-
- // main.cpp
- int main()
- {
- C& cc = testStatic3();
-
- std::cout << "cc: " << cc.getName() << std::endl; // 静态对象存储在静态存储区, 所以离开函数作用域后,仍然存在
-
- return 0.
- }
输出:

与类的静态成员变量类似,类的静态方法也属于类,任何类的对象都可以调用此类方法。
既可以通过 对象名. 静态方法 调用,也可以通过类名::静态方法,后一种方法更常用。
- // c.h
- #include
- #include
-
- class C
- {
- public:
- C(std::string n):name(n)
- {
- std::cout << "constructor C name: " << this->name << std::endl;
- }
- ~C(){
- std::cout << "destructor C name: " << this->name << std::endl;
- }
-
- std::string getName()
- {
- return this->name;
- }
-
- static void print()
- {
- std::cout << "print height: " << height << std::endl;
- }
-
-
-
- private:
- public:
- std::string name;
-
- static int height;
- };
-
- // c.cpp
- #include "c.h"
-
-
- int C::height = 66;
-
-
- // main.cpp
- #include"c.h"
- #include
-
- void testStatic4()
- {
- C::print();
- C c("888");
- c.print();
- }
-
- int main()
- {
- testStatic4();
-
- return 0;
- }
C++中static变量的初始化_c++ static 重新初始化_LikeMarch的博客-CSDN博客
三种初始化:
1. 编译时初始化
2. 程序加载时初始化
3. 运行时初始化
若 静态全局变量 是 基本数据类型(POD) ,且初始化值为常量,那么该变量会在编译期初始化。
- / main.cpp
-
- static int xx = 666;
-
- int main()
- {
-
- return 0;
- }
程序被加载时立即初始化,该过程发生在main 函数执行前。即使程序任何地方都没访问过该变量,仍然会进行初始化,因此形象地称之为"饿汉式初始化"。
2.1 静态全局变量初始化(初始值不是常量时),此时变量初始化是在程序加载时初始化的。
- // main.cpp
-
- int x = 6;
- int y = 8;
- static int z = x + y;
-
- int main()
- {
-
- return 0;
- }
2.2 静态全局变量不是基本类型,此时变量初始化是在程序加载时初始化的。
- // d.h
- #include
- #include
-
- class D
- {
- public:
- D(std::string n):name(n)
- {
- std::cout << "constructor D name: " << this->name << std::endl;
- }
- ~D()
- {
- std::cout << "destructor D name: " << this->name << std::endl;
- }
-
- private:
- std::string name;
- };
-
- // c.h
- class C
- {
- public:
- C(std::string n):name(n)
- {
- std::cout << "constructor C name: " << this->name << std::endl;
- }
- ~C(){
- std::cout << "destructor C name: " << this->name << std::endl;
- }
-
- std::string getName()
- {
- return this->name;
- }
-
- static void print()
- {
- std::cout << "print height: " << height << std::endl;
- }
-
-
-
- private:
- public:
- std::string name;
-
- static int height;
- static D d;
- };
-
- // c.cpp
- int C::height = 66;
-
- D C::d = D("CD static");
-
- // main.cpp
- #include
- #include
- #include"c.h"
-
- void testStatic5()
- {
- C c("testStatic5 -- ");
- std::cout << "testStatic5 c name: " << c.getName() << std::endl;
- }
-
- static D d("before main inialiaze!");
-
- int main()
- {
-
- std::cout << "enter int main func!!" << std::endl;
- testStatic5();
-
- return 0;
- }

程序执行到静态变量的定义引用时,才会初始化,因此也被称为“懒汉式初始化”。
比如静态局部变量就是典型的 运行时初始化。
- // d.h
- class D
- {
- public:
- D(std::string n):name(n)
- {
- std::cout << "constructor D name: " << this->name << std::endl;
- }
- ~D()
- {
- std::cout << "destructor D name: " << this->name << std::endl;
- }
-
- public:
- std::string name;
- };
-
-
- // main.cpp
-
- #include
- #include"d.h"
-
-
- void testStaticInitialize(){
- static D d("testStaticInitialize --- ");
- }
-
- int main()
- {
- std::cout << "enter int main func!!" << std::endl;
- static D dd("dd --- ");
- testStaticInitialize();
-
- return 0;
- }
-
输出:
