static关键字
在函数体中
static关键字作用在函数体内部的变量,也就是局部静态变量
存储位置不同的局部变量存储在栈中
而被static修饰的局部变量存储在静态存储区中,即使函数退出,他也不会被销毁
cppvoid test1() { int a, b; static int c; printf("a: %p\n", &a); printf("b: %p\n", &b); printf("c: %p\n", &c); } // 输出: // a: 0x7fffd8bbe550 // b: 0x7fffd8bbe554 // c: 0x584bef710018上面例子可以发现,a和b的地址是紧邻的,而和他们声明在一起的c的地址则没有
生命周期普通局部变量在进入函数时创建,退出函数时销毁
静态局部变量在程序启动时分配内存,在程序结束时释放,它的生命周期贯穿整个程序
作用域局部静态变量,名字已经很清楚了,他的作用域只能是在这个函数内部,函数外是无法访问的。但是每次调用这个函数的时候,访问的都是同一个静态变量
cppvoid counter() { static int count = 0; // 静态局部变量 count++; cout << "调用次数: " << count << endl; } int main() { for (int i = 0; i < 3; i++) counter(); return 0; } // 输出 // 调用次数: 1 // 调用次数: 2 // 调用次数: 3
在模块中
c/c++中的模块一般指的是某个源文件或者一个头文件被多个源文件包含的情况,此时static关键字的核心作用是限制符号(变量或函数)只能在当前编译单元中可见,也就是说,它限制了符号的连接属性,从"外部链接"变为"内部链接"
cpp// file1.cpp int a=0; static int b=0; void increase() { a++; b++; std::cout << a << " " << b << std::endl; } static void increase2() { a++; b++; std::cout << a << " " << b << std::endl; } // file2.cpp extern int a; extern void increase(); extern int b; extern void increase2(); int main() { increase(); // 可以,increase函数没有被static限制 increase2(); // 不可以 std::cout << a << std::endl; // 可以 std::cout << b << std::endl; // 不可以 }注意,你只写
extern int bextern void increase2()是不会报错的,这时候你只是告诉编译器我要从其他文件中引用一个变量一个函数,但是当你使用他们的时候,编译器就得去找你使用的到底是哪个变量哪个函数了,然后因为b和increase2()是内部链接的,编译器发现找不到,此时就会报错undefined未定义
在类中
static作用在类中,包括作用在类成员变量和类成员函数,称为类的静态成员,此时static关键字的核心作用是让该成员属于类本身,而不属于某个对象
修饰类成员变量特点:
- 归属:static修饰的成员属于类,而不属于某个对象;
- 内存:所有对象共享一份静态成员的内存,而不是每个对象一份;
- 访问方式:建议
类名::变量名,也可以对象.变量名- 定义:必须在类外单独定义并初始化
cppclass Counter { public: static int count; // 声明静态成员变量 Counter() { count++; } }; // 在类外定义并初始化 int Counter::count = 0; int main() { Counter a, b, c; cout << Counter::count << endl; // 输出:3 return 0; }
修饰类成员函数
特点:
- 调用方式:建议
类名::函数名()- 限制:不能访问类的非静态成员变量或函数
- static修饰类成员函数的目的通常是用于访问静态数据或与对象无关的操作
cppclass Counter { private: int id; static int count; public: Counter() { count++; } static void showCount() { // 静态成员函数 cout << "当前对象数: " << count << endl; // cout << id; 错误:不能访问非静态成员 } }; int Counter::count = 0; int main() { Counter a, b; Counter::showCount(); // 通过类名调用 a.showCount(); // 也可以通过对象调用 return 0; }