C++中的变量作用域介绍

技术交流QQ群:1027579432,欢迎你的加入!

1.Cpp的变量作用域

  • 作用域是程序的一个区域,一般来说有三个地方可以定义变量:
    • 局部变量:在函数或一个代码块内部声明的变量
    • 形式参数:在函数参数的定义中声明的变量(稍后介绍)
    • 全局变量:在所有函数外部声明的变量

2.局部变量

  • 在函数或一个代码块内部声明的变量,称为局部变量,它只能被函数内部或代码块内部的语句使用。如下:
// 局部变量声明,没有为其分配内存空间
int main(){
    // 局部变量声明,没有为其分配内存空间
    int a, b;
    int c;
    // 实际初始化
    a = 10;
    b = 20;
    c = a + b;
    cout << "c = " << c << endl;

    return 0;
}

3.全局变量

  • 在所有函数外部定义的变量(通常在程序的开始处),称为全局变量。全局变量从定义处开始至程序结束起作用,即全局变量存在有效作用域,全局变量的值在程序的整个生命周期内都是有效的。全局变量可以被任何函数访问,即全局变量一旦声明,在整个程序中都是可以用的,如:
// 全局变量的声明
int g;

int main(){
    // 局部变量声明,没有为其分配内存空间
    int a, b;
    int c;
    // 实际初始化
    a = 10;
    b = 20;
    c = a + b;
    cout << "c = " << c << endl;

    return 0;
}

4.全局变量与局部变量同名的情况

  • 在程序中,局部变量与全局变量的名称可以相同,但在main函数内部时,局部变量的值会覆盖全局变量的值。但是在子函数内的局部变量与全局变量是两个独立的变量,互不影响,如:
//-----------------------------------------------------//
但是,在子函数内的局部变量与全局变量是两个独立的变量,互不影响
int func();  // 子函数声明

// 全局变量的声明
int g = 233;


int main(){
    // 局部变量声明,没有为其分配内存空间
    int a, b, kk;
    int c;
    // 实际初始化
    a = 10;
    b = 20;
    c = a + b;
    cout << "c = " << c << endl;
    // 全局变量与局部变量同名时,局部变量会覆盖全局变量的值
    int g = 666;
    cout << "g = " << g << endl;
//------------------------------------------------------------------------//
    // 在程序中,全局变量与局部变量的名称可以相同,但是在子函数内的局部变量与全局变量是两个独立的变量,互不影响
    kk = func();
    cout << "kk = " << kk << endl;
    return 0;
}
// 子函数定义
int func(){
    return g;
}

  • 在一个函数体内可以存在重名的变量,前提是它们的作用域不同,如下:
        int aa = 22;
        {
            int aa = 77;
            cout << "inner aa = " << aa << endl;
        }
        cout << "outer aa = " << aa << endl;
    
    • 分析:当变量间出现重名的情况下,作用域小的屏蔽作用域大的,所以上面第一个 cout 输出 aa 的值为77,但由于在块里面申请的变量作用域只限于当前块,所以离开这个块后变量会自动释放,所以第二个 cout 输出 aa 的值为22。
  • 全局变量的值可以在局部函数内重新赋值
// 全局变量声明
int g = 20;
int fun1(int a,int b){
    g=a+b;
    cout<<"被改变的全局变量为:"<<g<<endl;
    return 0;
}

int fun2(){
    cout<<"此时的全局变量为:"<<g<<endl;
    return 0;
}

int main(){
    fun2();
    fun1(10,20);
    fun2();
    return 0;
}
  • 若要想让 main 函数也使用全局变量 a,可以用 extern 对全局变量进行声明,就可以合法使用
#include<iostream>
using namespace std;

int main()
{
     extern int a;
     cout<<"a= "<<a<<endl; //合法,输出10
     return 0;
}
int a=10; //全局变量从此处定义

5.静态变量

  • 存储在静态数据区的变量会在程序刚开始运行时就完成初始化,也是唯一的一次初始化。共有两种变量存储在静态存储区:全局变量和static变量,只不过和全局变量比起来,static可以控制变量的可见范围,说到底 static 还是用来隐藏的,虽然这种用法不常见。
  • 如果作为 static 局部变量在函数内定义,它的生存期为整个源程序,但是其作用域仍与自动变量相同,只能在定义该变量的函数内使用该变量。退出该函数后, 尽管该变量还继续存在,但不能使用它。
#include <iostream>
using namespace std;

int count = 1; //全局变量

int fun()
{
    static int count = 10; // 在第一次进入这个函数的时候,变量 count 被初始化为 10!并接着自减 1,以后每次进入该函数,count 的值是上一次函数运行之后的值
    return count--;        // 就不会被再次初始化了,仅进行自减 1 的操作;在 static 发明前,要达到同样的功能,则只能使用全局变量
}
 
//int count = 1; //全局变量
 
int main()
{
     cout<<"global  "<<"local staic"<<endl;
     for(int i = 1; i <= 10; ++count)
        cout<< i <<"        "<< fun() <<endl;
     return 0;
}
  • 全局变量和和局部变量同名时,可通过域名在函数中引用到全局变量,不加域名解析则引用局部变量
#include<iostream>
using namespace std;

int a = 10;
int main()
{
    int a = 20;
    cout << ::a << endl;   // 10
    cout << a << endl;     // 20
    return 0;
}

6.初始化全局变量和局部变量

  • 当局部变量被定义时,系统不会对其初始化,必须自行初始化。定义全局变量时,系统会自动进行初始化。正确初始化变量是一个良好的编程习惯,否则有时候程序会产生意想不到的结果。全局变量自动初始化的值如下:


    全局变量自动初始化的值.png

7.Cpp中全局变量,局部变量,静态全局变量,静态局部变量对比

  • C++ 变量根据定义的位置的不同的生命周期,具有不同的作用域,作用域可分为6种:全局作用域,局部作用域,语句作用域,类作用域,命名空间作用域和文件作用域。
    • 7.1 从作用域来看:
      • 全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件,包含全局变量定义的源文件还需要用extern 关键字再次声明这个全局变量。
      • 静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。
      • 局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
      • 静态全局变量也具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被static关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。
    • 7.2 从分配内存空间来看:
      • 全局变量,静态局部变量,静态全局变量都在静态存储区分配空间,而局部变量在栈里分配空间。
      • 全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于非静态全局变量的作用域是整个源程序,当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效,在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用,因此可以避免在其它源文件中引起错误。
      • 从以上分析可以看出, 把局部变量改变为静态变量后是改变了它的存储方式即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域,限制了它的使用范围。因此static 这个说明符在不同的地方所起的作用是不同的,应予以注意。
      • Tips:
        • 若全局变量仅在单个C文件中访问,则可以将这个变量修改为静态全局变量,以降低模块间的耦合度;
        • 若全局变量仅由单个函数访问,则可以将这个变量改为该函数的静态局部变量,以降低模块间的耦合度;
        • 设计和使用访问动态全局变量、静态全局变量、静态局部变量的函数时,需要考虑重入问题,因为他们都放在静态数据存储区,全局可见;
        • 如果我们需要一个可重入的函数,那么,我们一定要避免函数中使用static变量(这样的函数被称为:带“内部存储器”功能的的函数)
        • 函数中必须要使用static变量情况:比如当某函数的返回值为指针类型时,则必须是static的局部变量的地址作为返回值,若为auto类型,则返回为错指针。
  • 静态全局变量:改变作用范围,不改变存储位置
  • 静态局部变量:改变存储位置,不改变作用范围
  • 静态函数 :在函数的返回类型前加上static关键字,函数即被定义为静态函数。静态函数与普通函数不同,它只能在声明它的文件当中可见,不能被其它文件使用。
  • 如果在一个源文件中定义的函数,只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用,这种函数也称为内部函数。定义一个内部函数,只需在函数类型前再加一个“static”关键字即可。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352