参考自黑马程序员C语言基础(第七天)内存管理_Dontla的博客-CSDN博客
目录
1 作用域
变量或函数的可见范围,一共有三种作用域:
(1)代码块作用域,即 {} 围起来的一块作用域。
(2)函数作用域,即函数中的局部变量。
(3)文件作用域,即一个.cpp文件
2 局部变量
定义
在 {} 中定义的变量就是局部变量。
作用域
其只在 {} 内部有效。
生命周期
只有当执行到定义这个变量的语句时,系统才会给这个变量分配空间。
如果没有赋初值,则随机初始化。
当执行到离开 {} 时,如果这个局部变量是非static的,则自动释放。
3 全局变量
定义
在 {} 中定义的变量。
作用域
只要定义了全局变量,在任何地方都能使用(也就是说可以跨文件使用)。
即在一个文件中如果定义了全局变量,那么在定义语句之后都可以使用该全局变量。
如果在另一个文件中要使用该全局变量,则要用extern声明一次该变量即可。即全局变量只能定义一次,但是在不同的文件中使用时可以声明多次。同时也说明了,extern关键字只能用于声明全局变量,不用于局部变量。
生命周期
全局变量在编译阶段已经分配空间,只有整个程序结束,才主动释放。
全局变量如果不初始化,则默认初始化为0。
main.cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
extern void test();
test();
extern int a;
extern int b;
a = 100;
b = 50;
test();
return 0;
}
func.cpp
#include<bits/stdc++.h>
using namespace std;
int a = 10;
int b = 5;
void test(){
cout<<a<<" "<<b<<endl;
}
输出:
需要注意的是函数是默认全局的,但是在一个文件中使用其它文件中定义的函数的时候可以用extern声明,也可以省略extern,比如上边代码中extern void test(); 直接改成void test(); 完全没问题,但是对于变量a和b来说,extern是不能省略的,
4 静态变量
静态局部变量
定义
在{}中定义的static变量。
作用域
定义的{}内
生命周期
static在编译阶段就已经分配空间,即在{}对应函数或代码块调用之前,static局部变量就已经存在,当程序离开{}后,它依然存在,直到程序结束才释放。
如果static局部变量不初始化,会默认初始化为0。且static局部变量初始化语句只会执行一次,即便其在一个循环中也只会执行一次。
static局部变量只能用常量初始化,不能用变量。
静态全局变量
定义
在{}之外定义的static变量
作用域
只有定义的本文件能使用,即普通全局变量所有文件都能使用,只不过跨文件使用需要extern声明,但是static全局变量把全局变量的作用域限制在了本文件内。普通全局变量即使跨文件也不能重名,但是static全局变量跨文件重名完全没问题,因为本来就相当于两个变量。
函数默认是全局的,所有不同文件中函数不能重名。
static函数则把函数作用域限制在本文件,因此不同文件中可以出现重名静态函数。
生命周期
与程序运行周期一样,而且也是只能初始化一次。
类的静态成员变量/函数
初始化静态成员变量要在类的外边进行,不能用参数初始化列表对静态成员变量初始化,其实是不能用构造函数初始化吧,因为静态成员变量属于整个类,在编译阶段分配空间,整个程序结束才释放,可以用类名也可以用对象名来引用。
数据类型 类名::静态成员变量名 = 初值;
我们知道C++类的静态成员变量是需要初始化的,但为什么要初始化呢。其实这句话“静态成员变量是需要初始化的”是有一定问题的,应该说“静态成员变量需要定义”才是准确的,而不是初始化。两者的区别在于:初始化是赋一个初始值,而定义是分配内存。静态成员变量在类中仅仅是声明,没有定义,所以要在类的外面定义,实际上是给静态成员变量分配内存。
静态成员函数也是属于整个类,普通成员函数在参数传递时编译器会隐式传递一个this指针,即普通成员函数内是可以直接使用this指针的,通过这个this指针确定调用类的是哪个对象,但是静态成员函数没有this指针,所以静态成员函数只能访问静态成员变量,不能访问普通变量。即一句话:
非静态可以访问静态,静态不可以访问非静态。