1.4c变量的作用域

从1.3节我们已经得知,当CPU执行int x;时,一个名为x的变量就会被创建,那么接下来自然就会问,这个变量什么时候会被销毁(释放占用的内存)呢?

变量的作用域决定了在其生命周期中,谁可以“看见”和使用这个变量。不管是函数参数,还是函数体中声明的变量,都有其作用域。局部变量在定义时被创建,离开作用域后被销毁。

考虑下面的程序:

#include <iostream>

int add(int x, int y) // x、y在这里被创建
{
    // x、y仅在该函数中可见/可用
    return x + y;
} // x、y离开此作用域后就会被销毁

int main()
{
    int a = 5; // a被创建并初始化
    int b = 6; // b被创建并初始化
    // a、b仅在此函数中可用
    std::cout << add(a, b) << std::endl; // 调用函数add(),令x=a,y=b
    return 0;
} // 离开此范围后a、b被销毁

当函数add()被调用时,参量x、y被创建,且仅在函数add()中可见/可用,调用函数结束后就会被销毁。

变量a、b在main()函数中被创建,且仅在main()中可见/可用,main()结束后就会被销毁。

为了强化你的理解,我们来更详细地跟踪程序的执行过程。

  • 执行main()函数
  • main中的变量a 被创建并被赋值5
  • main中的变量b 被创建并被赋值6
  • 将a、b作为实参调用函数add()
  • add中变量x 被创建并被赋值5
  • add中变量y 被创建并被赋值6
  • 操作符+将5、6相加得到11
  • 将11作为返回值返回给main()
  • add的x、y变量被销毁
  • main将11打印到控制台
  • main向操作系统返回0
  • main的a、b变量被销毁

注意如果函数add()被调用两次,x、y就会被创建和销毁两次,在多函数的程序中,变量的创建和销毁是很频繁的。

作用域避免了命名冲突

在上述程序中,变量a、b与x、y是很容易区分的。现在我们再来看这个程序:

#include <iostream>

int add(int x, int y) // add中x变量被创建
{
    return x + y;
} // add中x被销毁

int main()
{
    int x = 5; // main的x变量被创建
    int y = 6;
    std::cout << add(x, y) << std::endl; // main中x的值被传递给add中的x
    return 0;
} // main的x被销毁

在这个程序中,我们将a、b的名称改为x、y,程序依然可以正常运行,尽管main() 和add()中都有名为x、y的变量。为什么没有产生命名冲突呢?因为main()中x、y的作用域仅在main()函数中,对add()函数是不可见的。add()和main()都不知道对方有与自己变量名称相同的变量。

这样就避免了命名冲突,作用域使得函数无须关心其他函数是如何命名自己的变量的。也避免了一个函数在不经意间(或故意地)更改其他函数中变量的值。

第四章中还会讲到这个话题。

规则:函数的参量与函数体中声明的变量仅对该函数可见。

小测验

下面的程序会输出什么?

#include <iostream>

void doIt(int x)
{
    x = 3;
    int y = 4;
    std::cout << "doIt: x = " << x << " y = " << y << std::endl;
}

int main()
{
    int x = 1;
    int y = 2;

    std::cout << "main: x = " << x << " y = " << y << std::endl;

    doIt(x);

    std::cout << "main: x = " << x << " y = " << y << std::endl;

    return 0;
}

答案

main: x = 1 y = 2

doit: x = 3 y = 4

main: x = 1 y = 2

转载请参看关于博客页面相关要求。