C++ 函数作用域

来源:互联网 发布:取消映射网络驱动器 编辑:程序博客网 时间:2024/06/05 22:41

变量作用域

局部作用域、全局作用域、文件作用域

 

局部变量:也称内部变量,声明在函数内(包括main函数),作用域开始于变量声明之处,结束于函数或块结束处;

 

全局变量:也称外部变量,声明在函数外,作用域一般是整个程序源文件,作用域最广,甚至可以作用于组成该程序的所有源文件(比如,将多个独立编译的源文件链接成一个程序时,在某个源文件中声明的全局变量,在与该源文件相链接的其他源文件中也可以使用,但使用前必须进行extern全局声明。这样,多个源文件中的所有函数都能使用全局变量,在一个函数中改变了一个全局变量的值,就会作用到使用该全局变量的其他所有函数,相当于各函数之间有了一条直接传递数据的通道。当然这也破坏了独立性)

 

文件作用域:在函数外部声明的变量只在当前文件范围内(包括文件内所有定义的函数)可用,在其他文件不可用。要使变量具有文件作用域,必须在变量的声明前加static关键字。当多个源文件链接成一个程序时,static可以避免一个文件中的全局变量与其它文件中的变量同名而发生冲突。

 

在同一作用域内的变量不能同名,但在不同作用域内的变量可用同名,在本作用域会覆盖/屏蔽其它作用域的同名变量。(我的地头我做主)

 

1. static全局变量和普通全局变量区别?

在全局变量声明前加static -> static全局变量,全局变量本身是静态存储方式,静态全局变量也是静态存储方式,在存储方式上无区别。

主要区别在于非静态全局变量的作用于是整个源程序(由多个源程序组成的话,在各个源文件中都有效);静态全局变量限制了作用域,只在定义该变量的源文件中有效(全局作用域->文件作用域),可避免在其他文件中引起错误。static变量只初始化一次,下一次依照上一次的值

 

2. static局部变量和普通局部变量区别?

在局部变量声明前加static -> 静态局部变量,存储方式改变了,局部变量是动态存储,静态局部变量是静态存储方式,也就是改变了它的生存期,由函数内部或者块内部变为文件作用域,虽然并不是真正的“文件作用域”,声明在函数内,但是在函数外部无法访问,作用应该只是为了避免重名冲突。

 

PS: 静态局部变量扩大了局部变量的生存期,静态全局变量缩小了全局变量的作用域

 

3. static函数与普通函数区别?

静态函数与普通函数作用域不同,仅在本文件。内部函数:只在当前源文件中声明和定义的函数称为内部函数(static);对于可在当前源文件以外使用的函数,应该在头文件中说明,或者进行extern全局声明。static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝。

 函数的存储类型

分为内部函数(static) 和外部函数(extern)两类。内部函数:只能被同一个源文件中的函数所调用;外部函数:可以被其他源文件中的函数所调用。

没有定义存储类型的函数默认extern。

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

变量的存储类型

任何变量都有数据类型和存储类型两种属性。完整的变量声明,除了声明代表变量运算属性的数据类型,有时还需要声明代表变量存储方式的存储类型。

除了分配内存空间大小,还要分配不同类型的内存空间。

变量的存储类型决定了C++编译器为变量分配内存的方式,决定了变量的生存期

 

准确来说,变量的生存期和作用域是从不同角度分析变量的属性。

 

变量的作用域:空间范围,从代码空间角度,哪段代码看得见,哪段代码看不见。关键是“可见性”和“可用性”。

变量的生存期:从代码的执行时间角度考虑,是指在程序执行的过程中变量从创建到被撤销的一段时间,即变量的生命周期。当变量被分配了内存空间,就处于生存期;当所占的内存空间被释放,这个变量就结束了生存期。关键是“存活状态”。

 

最明显的就是静态局部变量。

// 静态局部变量使用

void fun()

{

static int a;//静态变量a是局部变量,但具有全局变量的生存期

a++;

cout << "a = "<< a<<endl;

}

 

int main()

{

for(int i = 0; i < 2; i++)//静态变量a不在作用域内

fun();

}

结果是

a = 1

a = 2

 

分析:声明静态变量时如果没有初始化,则“初始化”值为0,静态全局变量的初始化是在执行main之前完毕,静态局部变量的初始化是在程序运行后第一次执行该变量的声明语句时进行。

 

 

下例:在MyFunc()中第一个声明的局部变量(x=1)在随后的语句块中虽然处于生存期(因为声明和定义它的MyFunc()函数块还没有结束),但不在作用域,因为被语句块内同名的局部变量x(2)屏蔽(/覆盖)了,但是一旦语句块结束,x(2)的生存期也就结束了,在MyFunc()内只有x = 1生存。局部变量x(2),y(2)虽然在语句块内生存,但进入函数FuncA()后也是不可用的。

 

void MyFunc(){

int x = 1;

{

int x(2),y(2);//变量" x = 1"失去作用域

cout << "x = "<<x<<"\n";

FuncA(); //变量X(2),Y(2)进入函数后失去作用域

}

}

 

内存的分配方式:自动分配,静态分配,动态分配,所占内存区域和变量类型如下:

 



静态分配
:编译时就分配了内存地址,运行时变量就占用内存,知道程序结束时变量才释放内存。 

 

动态分配:利用堆(heap)这个内存块为变量分配内存,堆使用了除栈、静态存储区之外的自由存储空间。是一种完全由程序自身控制内存分配的方式(控制包括开辟空间new、释放空间delete

 

对于非动态内存分配方式的变量,决定变量采用哪种内存分配方式,是由声明变量时指定存储类型和声明语句在程序中的位置决定的。

C++变量的存储类:

auto, register, extern, static

声明时可指定:

<存储类型>  <数据类型>  <变量名列表>;

 

auto int a;

static float b,c;

 

registerauto声明局部变量:register存储在寄存器,auto存储在栈

extern声明全局变量,static声明全局变量和局部变量

externstatic都在静态存储区。

 

没有指定存储类型,默认如下:

局部变量:auto

全局变量:extern

 

 

全局变量:定义性声明和引用性声明

定义性声明定义变量,分配内存空间。只能在函数外部,一般不加extern

引用性声明表示变量已经在程序源文件中其他地方进行过定义性声明(已分配空间)。可以放在函数外,也可以放在函数内,要加extern,一般不能对变量初始化,除非定义性声明没有初始化。

 

程序有多个源文件组成,如果每个文件都要使用同一个全局变量,在每个文件中都要进行全局变量的声明,但如果是定义性声明,编译每个源文件不会出错,链接它们则出现重复定义错误。所以方法是在一个源文件中进行定义性声明,其它文件引用性声明。

0 0
原创粉丝点击