之前对 static
的理解仅限于:在类中声明这种类型的变量,可以通过这个变量知道这个类被创建了多少个对象。但是前些日子刷 leetcode
的时候,发现类中自定义的 cmp
函数如果不是 static
类型,就无法被类内的 sort
函数识别。所以今天来一探究竟。
面向过程
其实 C 语言中也有 static
这个关键字,在全局区分配内存,或者说可以理解为全局变量,来回顾一下:
- 在全局区分配内存,自动初始化为 0,注:全局区就是静态区
- 在声明的整个文件是可见的
- 不会因子函数的退出而被释放空间,即子函数被执行完成初始化后,之后的调用不会再初始化,但作用域是局部的
- 修饰普通函数,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命名空间里的函数重名,可以将函数定位为 static。
全局变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| #include <iostream>
static int test;
void sub_func() { test += 1; }
int main() { test += 1; std::cout << test << std::endl; sub_func(); std::cout << test << std::endl; return 0; }
|
局部变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| #include <iostream>
void sub_func() { static int test; test += 1; std::cout << test << std::endl; }
int main() { sub_func(); sub_func(); return 0; }
|
面向对象
static 成员变量
- 这个类的所有对象都可以访问静态成员变量,一个对象修改,其他对象也会改变。说高级一些,不随对象创建而分配内存,不随对象销毁而释放内存
- 存储在全局区
- 必须类外初始化
- 可以通过类名访问
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| #include <iostream>
class A{ public: static int num; A(){ A::num += 1; } void increase(int a) { A::num += a; } };
int A::num = 0;
int main() { A a; A b; std::cout << A::num << std::endl; b.increase(18); std::cout << A::num << std::endl; return 0; }
|
成员函数
- 静态成员函数仅可以访问静态成员、函数;不能访问非静态成员、函数
- 非静态成员函数可以任意访问静态成员、函数
- 不需要
this
指针的额外操作
- 可以通过类名访问
来看一个 static
的成员函数,顺便解答本文开始的疑问。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| #include <iostream> #include <algorithm> #include <vector>
class A{ public: static int num; int a = 10; static auto get_num() { return A::num; } static bool cmp(int& a, int& b) { return a > b; } void sort(std::vector<int>& arr) { std::sort(arr.begin(), arr.end(), cmp); } };
int A::num = 0;
int main() { A a; A b; std::vector<int> arr{3, 2, 4, 6, 2, 5, 7}; a.sort(arr); for (auto i : arr) { std::cout << i << " "; } return 0; }
|
::
扩展
上面写了很多 ::
,江湖人称范围解析运算符,顺手总结一下:
::variable
,全局作用域符,作用域是全局空间,如 ::isspace
class::variable
,某个类的作用域范围
namespace::variable
,某个命名空间的作用域范围。重点是,static
声明的链接性为内部静态变量的东西,可以使用未命名的 namespace
代替。