(易错)C++的作用域概念

这不对吧?从一个例子讲起

请读者先仔细观察下面的代码

1
2
3
4
5
int a=8;
if (a<9){
    int b=a;
}
cout<<b;

提问:上面会输出什么?

你心想:这还用问,b=a=8,当然输出8了。

然而,结果却是

b未定义

'b' was not declared in this scope

这不对吧?为什么b是未定义的?这是因为c语言中有作用域的概念。

代码块

c++中用花括号 { } 标识一个代码块, { } 内的所有语句被视为一句语句。在if,while,for等控制语句中经常用到。

块级作用域

c语言规定 { }里新定义的变量,只能在当前{ }里使用 ,即 块级作用域

1
2
3
4
int a;
    {
        int b;
    }

上面 { } 内的变量b,只能在 { } 里使用。

下面的例子更是典型:

1
2
3
4
for(int i=0;i<8;i++){
    continue;
}
cout<<i<<endl;

上面的输出是什么?

答案不是输出9。因为这里的for语句就是一个代码块,在里面新定义的变量只能在for语句中使用。

想让for语句结束后输出变量i,那么变量i必须在for语句之前定义。

下面两种方案是可行的:

1
2
3
4
5
int i;
for(i=0; i<8; i++){
    continue;
}
cout<<i<<endl;

1
2
3
4
5
int i=0;
for(; i<8; i++){
    continue;
}
cout<<i<<endl;

作用域遮蔽(Shadowing)

{ } 代码块外部若已定义一个变量,在 { } 里允许对该变量重新定义,且仅在该代码块内失效。

1
2
3
4
5
6
int a=0;
    {
        float a=5.6;
        cout<<a<<endl;
    }
cout<<a<<endl;

输出 $5.6$ 和 $0$

函数作用域

在自定义函数里定义的普通变量,是局部变量,仅在该函数体内可用。

特别要注意的是,main函数也是函数,在main里定义的变量在自定义函数里是无法直接使用的。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
...
int main(){
    int a=5;
    couta();
    ...
}

void couta(){
    cout<<a<<endl;
}

这里couta函数无法使用a,因为a是main的局部变量。

要想在couta()里使用a,可以在main前初始化a。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
...
int a;

int main(){
    a=5;
    couta();
    ...
}

void couta(){
    cout<<a<<endl;
}

总结

块级作用域 { },可以简单理解成中央与地方的关系。

{ } 外面的变量相当于是中央文件, { } 内部的变量看作地方法规。中央出台的文件对所有地方省份都生效,各省份可以根据自身情况修改中央文件,或者制定新的法规。地方修改后的中央文件和新法规也仅对该区域生效,不会影响到中央和其他地方省份。

小测

1

下面的for循环可以完整输出字符数组strA的所有内容吗?如果不能,请改正。

1
2
3
4
5
6
7
8
...
int i=0,j=0;
char strA[2][6]={"Hello","world"};
for (; i<2; i++){
    for (; j<5; j++){
        cout<<strA[i][j];
    }
}

2

下面的语句能不能判断a是不是质数?如果不能,请更正。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
...
int a;
a=11;
for(int i=2; i<2; i++){
    if (a/i==0){
        break;
    }
}
if (i==a){
    cout<<a<<"是质数"<<endl;
}
else{
    cout<<a<<"不是质数"<<endl;
}

3

思考下面代码的运行结果:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
...
int a,b,c;
a=3,b=5,c=8;
{
    c=b;
    int b=a;
    cout<<b<<' ';
}
cout<<b<<' ';
cout<<c;
Licensed under CC BY-NC-SA 4.0
使用 Hugo 构建
主题 StackJimmy 设计