C/C++中static关键字用法总结

发布时间:2026/7/30 17:21:58
C/C++中static关键字用法总结 C基础专栏http://t.csdnimg.cn/4FdOH目录1.引言2.静态局部变量3.静态全局变量4.静态函数5.静态成员变量6.静态成员函数7.使用误区:头文件用static修饰全局函数8.总结1.引言在面试的过程面试官经常都会问到static关键字有哪些用法在C/C中各有些什么作用今天就在这里我们好好的总结一下static的全方位用法。2.静态局部变量局部变量也就是定义在函数内部的变量函数局部变量存放在栈区该变量的生命周期由所在 {} 决定进入 {} 作用范围而分配内存空间退出 {} 作用范围而释放内存空间。在局部变量的前面加上static变成静态局部变量即使多次调用该函数静态变量的空间也只分配一次。C/C中{}的用法总结(全)_c {}-CSDN博客定义在函数体内的变量加上static修饰符它的存在意义是随着第一次函数的调用而初始化但却不随着函数的调用结束而销毁。因此静态局部变量保存在全局数据区而不是保存在栈中每次的值保持到下一次调用直到下次赋新值。设计模式之单例模式-CSDN博客示例如下#include iostream using namespace std; void test(void) { int a 1; // 局部变量 static int b 10; //静态局部变量 a; b; cout a: a , b: b endl; } int main() { test(); //输出: a1,b11 test(); //输出: a1,b12 test(); //输出: a1,b13 test(); //输出: a1,b14 return 0; }3.静态全局变量全局变量的空间会在程序的生命周期内分配在全局变量的前面加上static变成静态全局变量。静态全局变量在全局数据区分配内存那它和全局变量有啥区别呢全局变量不但在本文件中可以被访问在其他文件中同样可以访问。写代码时很容易在不同文件定义相同名字的全局变量这就会引发冲突。而静态全局变量只能在声明它的整个文件可见限制了该变量的访问范围。同样的静态全局函数在全局函数前加上static表示只能在声明文件中被访问。示例变量g_nTotalCount在static.cpp中定义为静态全局变量因此无法在main.cpp中使用运行会提示“无法解析的外部符号”。//static.pp #include iostream #include static.h using namespace std; static int g_nTotalCount 22222; //静态全局变量要想在main.cpp中使用需定义为全局变量 //int g_nTotalCount 22222; void func(void) { int x 11; cout x: x endl; }//static.h #include iostream void func(void);//main.cpp #include iostream #include static.h using namespace std; int b 2425; //全局变量 int main() { extern int g_nTotalCount; //申明静态全局变量运行失败想用g_nTotalCount则g_nTotalCount需定义为全局变量而不是静态全局变量 cout g_nTotalCount: g_nTotalCount endl; func(); return 0; }想使用static.cpp中的全局变量g_nTotalCount则需要定义为全局变量而不是静态全局变量。4.静态函数在普通函数定义前加上修饰符static就是静态函数作用和静态全局变量类似函数的定义和生命在默认状态下都是extern的但静态函数只是在申明他的文件当中可见不能被其余文件所用。5.静态成员变量一个类可以定义多个对象每个对象都会对类中的普通成员变量进行空间分配这些变量只由它所在对象使用。静态成员变量是该类的所有对象所共有的。对于普通成员变量每个类对象都有自己的一份拷贝而静态成员变量整个类就一份静态成员变量只分配一次内存类的所有对象都共享这个变量不属于任何一个类不需要对象就可以访问。静态成员变量不属于特定的对象不会占用对象的内存必须在类的外面进行初始化。对象的内存中只包括普通成员变量注意不包括任何成员函数。sizeof(类名) 不会计算静态成员变量和成员函数。普通成员变量随这对象的产生而产生静态成员变量随着类的产生而产生所以静态成员变量不能由构造函数初始化即使没有对象也可以访问静态全局变量。示例如下#include iostream #include string.h using namespace std; class MyTest { public: static int m_x; //声明静态成员变量 }; int MyTest::m_x 3242234; //定义并初始化静态成员变量 int main() { printf(m_x:%d, sizeof(MyTest):%d\n, MyTest::m_x, sizeof(m_x)); return 0; } //输出m_x:3242234 sizeof(MyTest)16.静态成员函数就像类中的静态成员变量一样静态成员函数也不依赖于类的对象不具体作用于某个对象。普通成员函数参数自带一个this指针this指针指向类的对象本身因为普通成员函数总是属于类对象当函数被调用时系统会把当前对象的起始地址赋给 this 指针。静态成员函数属于类本身因此不具有this指针。它无法访问属于类对象的非静态成员变量和非静态成员函数它只能访问其他静态成员变量和静态成员函数。可以通过对象来调用但还是建议使 类名::静态成员函数 调用静态成员函数。静态成员函数和静态成员变量在类实例化之前就已经存在可以访问而此时非静态成员还是不存在的因此静态成员函数不能访问非静态成员变量。示例如下#include iostream using namespace std; class A { public: static int a; //类的静态成员变量 static int get_a();//类的静态成员函数 int b; int get_b(); }; int A::a 100; //静态成员变量可以在类的外部直接定义 //int A::b 1000; //普通成员变量在类的外部定义失败 int A::get_a() { return a; //类的静态成员函数只能访问类的静态成员变量 //return b a; //静态成员函数无法调用普通成员变量 } int A::get_b() { return b a;//普通成员函数可以调用静态成员变量 } int main(void) { cout a: A::get_a() endl; //不需要类的实例也可以调用类的静态成员函数 A m; m.b 90; m.a 100000; cout m.get_a() endl; cout m.get_b() endl; cout m.a endl; return 0; }7.使用误区:头文件用static修饰全局函数头文件内static修饰全局函数 每个#include该头文件的.cpp都会独立生成一份函数实体文件域静态。若只是调用不会报错若多文件都实例化同一个模板/ 取函数地址、跨文件比对地址、链接时导出符号会出现冲突、重复定义、地址不一致诡异问题。static在全局作用域的语义限制符号仅当前翻译单元cpp可见a.cpp 引入头文件 → 生成一份 static 函数 Ab.cpp 引入头文件 → 再生成一份独立 static 函数 A 链接器看来是两个完全无关函数 但模板函数、inline 函数、外部变量场景极易触发冲突报错。解决方案inlineC 标准首选头文件写函数头文件函数用inline允许多翻译单元存在相同定义链接器自动合并// test.h #ifndef TEST_H #define TEST_H #include vector #include numeric #include cmath #include type_traits templatetypename T concept Arithmetic std::is_arithmetic_vT; // inline 修饰头文件直接实现 templateArithmetic T inline double absAvg(const std::vectorT vec) { if(vec.empty()) return 0.0; T sum std::accumulate(vec.cbegin(), vec.cend(), T{}, [](T s, T v){return s std::abs(v);}); return static_castdouble(sum)/vec.size(); } #endif优势支持多文件 include 无重复定义模板函数天然建议 inline不需要拆源文件。8.总结在使用关键字static的时候我们需要注意一下几个原则被static修饰的变量的存储位置都在静态区且生命周期延长至整个程序运行结束。static具有隔离作用被static修饰的全局变量和全局函数的作用域由全局变为当前文件。静态变量虽然具有全局变量的生命周期但只能作用于自己的作用域。普通静态成员需要在类的外面进行初始化。静态成员函数不能调用类的非静态成员包括非静态成员和非静态成员函数。