C++的作用域、变量作用域、生命周期和变量分类介绍

C++的作用域、变量作用域、生命周期和变量分类介绍

C++ 中的作用域(scope)指的是变量、函数或其他标识符的可见和可访问的范围。

变量作用域(Variable Scope)是指变量的生命周期和可见性,也就是变量在程序中的哪些部分可以使用。按照作用域(Scope)变量可分类为全局变量和局部变量。

还可按照生命周期(Lifetime)进行分类变量可分类为静态变量(Static Variables)和成员变量(Member Variables)。

C++的作用域(scope

C++中的作用域(scope)是指变量、函数和其他标识符的可见性和有效性范围。作用域规定了在程序中的哪些位置可以访问或引用某个标识符。参见Scope - cppreference.com

C++中有以下几种作用域:块作用域(Block Scope)、函数参数作用域(Function parameter scope)、命名空间作用域(Namespace Scope)、类作用域(Class Scope)、枚举常量作用域(Enum Constant Scope)、模板形参作用域(Template parameter scope)。

  1. 块作用域(Block Scope):代码块内部声明的变量拥有块作用域,只在该代码块内可见,包括循环、条件语句等。
  2. 函数参数作用域(Function Parameter Scope):函数参数也拥有自己的作用域,仅在函数内部有效,允许使用相同名称的局部变量隐藏函数参数。
  3. 命名空间作用域(Namespace Scope):命名空间中定义的标识符拥有命名空间作用域,可以在整个命名空间范围内访问。
  4. 类作用域(Class Scope):类成员(包括变量、函数等)拥有类作用域,可以在类内部访问,并通过对象或指针进行访问。
  5. 枚举常量作用域(Enum Constant Scope):枚举类型中的常量拥有常量作用域,只能在枚举类型内部访问。
  6. 模板形参作用域(Template Parameter Scope):模板类或函数中的模板形参拥有自己的作用域,只在模板定义内有效。

在C++中,作用域(Scope)和变量的作用域(Variable Scope)并不完全相同,尽管它们之间有密切关联。

作用域(Scope)是指标识符(如变量、函数等)在程序中可见和有效的范围。作用域规定了在哪些位置可以访问或引用某个标识符。作用域涵盖了整个程序,从全局范围到更小的范围(如代码块内部、函数内部等)。

变量的作用域(Variable Scope)则是指在程序中某个位置声明的变量可见和有效的范围。变量的作用域是作用域的一种应用,它决定了在何处可以使用该变量以及该变量的生命周期。

因此,作用域是一个更广泛的概念,可以包括各种标识符(如函数、类、命名空间等),而变量的作用域则专门指的是变量在程序中的可见性和有效性范围。

C++中变量的作用域(Variable Scope

在C++中,变量的作用域可以通过其声明的位置来确定。在不同的作用域内,变量的可见性和有效范围会有所不同。下面是几种常见的变量作用域。

★全局作用域(Global scope):全局作用域表示变量在整个程序中都可见。在任何函数或代码块之外声明的变量都具有全局作用域。这些变量在程序开始执行时创建,在程序结束时销毁。例如:

#include <iostream>
int x = 10; // 全局变量

int main() {
    std::cout << x << std::endl; // 输出:10
    return 0;
}

在上面的示例中,变量x在main函数中被访问,因为它具有全局作用域。

★函数作用域(Function scope):函数作用域表示变量仅在函数内可见。变量在函数内部声明,只能在同一函数内访问。函数作用域的变量在函数执行时创建,在函数结束时销毁。例如:

#include <iostream>

void printNumber() {
    int num = 5; // 函数作用域中的变量
    std::cout << num << std::endl; // 输出:5
}

int main() {
    printNumber();
    // std::cout << num << std::endl; // 错误:变量num不在作用域内
    return 0;
}

在上面的示例中,变量num仅在printNumber函数内部可见。

★代码块作用域(Block scope):代码块作用域表示变量仅在代码块内部可见。变量在任何代码块(例如if语句、循环等)内部声明,只能在同一代码块内或嵌套在此代码块内的其他代码块中访问。块作用域可以嵌套,内部代码块可以访问外部代码块中声明的变量,但反之则不行。例如:

#include <iostream>

int main() {
    if (true) { // 代码块作用域
        int num = 5; // 代码块作用域中的变量
        std::cout << num << std::endl; // 输出:5
        {
            std::cout << num << std::endl; // 输出:5,嵌套代码块中仍然可见
        }
    }
    // std::cout << num << std::endl; // 错误:变量num不在作用域内
    return 0;
}

在上面的示例中,变量num仅在if语句所在的代码块中可见。

★函数参数作用域(Function parameter scope):函数参数也具有自己的作用域,它们在函数内部有效。函数参数作用域指的是这些参数在整个函数内部可见。例如:

#include <iostream>

void printNumber(int num) { // 函数参数作用域中的变量
    std::cout << num << std::endl; // 输出由传入的参数值决定
}

int main() {
    printNumber(10); // 输出:10
    return 0;
}

在上面的示例中,函数参数num在整个printNumber函数内部可见。

注意,变量的作用域是通过声明位置来确定的,因此相同的变量名可以在不同的作用域中被使用。这样,它们代表的是不同的变量。当在内部作用域中声明与外部作用域中相同名称的变量时,内部作用域内的变量会隐藏外部作用域中的同名变量。例如:

#include <iostream>

int x = 5; // 全局变量

void printNumber() {
    int x = 10; // 局部变量,隐藏了全局变量x
    std::cout << x << std::endl; // 输出:10
}

int main() {
    std::cout << x << std::endl; // 输出:5,全局变量x
    printNumber();
    return 0;
}

在上面的示例中,函数printNumber内部声明的局部变量x隐藏了全局变量x,所以在函数内部输出的x值为10,而在main函数中输出的x值为5。

★类作用域(Class Scope):在类内部声明的变量具有类作用域,可以被类中的所有成员函数访问。类作用域的变量在对象创建时创建,在对象销毁时销毁。例如:

#include <iostream>

class MyClass {
public:
    int x; // 类作用域中的变量

    void printX() {
        std::cout << "类作用域中的变量:" << x << std::endl;
    }
};

int main() {
    MyClass obj;
    obj.x = 10; // 修改类作用域中的变量
    obj.printX(); // 输出类作用域中的变量

    return 0;
}

运行输出

类作用域中的变量:10

生命周期(Lifetime)

生命周期(Lifetime)指的是变量或对象存在的时间段。它开始于变量或对象的创建时刻,结束于其被销毁的时刻。

对于变量,生命周期包括了变量的创建、初始化、使用和销毁这几个阶段。在变量的创建阶段,内存空间被分配给该变量,并根据定义的类型进行初始化。在变量的使用阶段,可以对变量进行读取、修改等操作。最后,在变量的作用域结束或者显式释放内存时,变量会被销毁,其占用的内存空间被释放。

对于对象,生命周期也类似。对象的生命周期包括了对象的构造、使用和析构这几个阶段。在对象的构造阶段,会调用构造函数来初始化对象的成员变量。在对象的使用阶段,可以通过对象来调用其成员函数进行各种操作。最后,在对象不再被使用或者超出其作用域时,会调用析构函数来清理对象所占用的资源。

C++提供了灵活的方式来管理对象和变量的生命周期,如手动创建和销毁对象。

由程序员使用 new 运算符分配的变量被称为动态分配的变量。在C++中,new 运算符用于在堆内存(heap)上动态地分配内存空间,并返回指向该内存空间的指针。

与静态分配的变量(例如在栈上分配的局部变量)不同,动态分配的变量的生存期不受其作用域的限制。它们会一直存在,直到显式释放或删除。

通过new运算符分配的变量需要手动释放内存,以避免内存泄漏。使用delete运算符来释放动态分配的变量,以便将内存归还给系统。

以下是一个使用new和delete进行动态内存分配和释放的示例:

int* dynamicVariable = new int; // 动态分配一个整型变量

// 使用 dynamicVariable 进行操作

delete dynamicVariable; // 释放内存

请注意,动态分配的变量需要我们手动管理其生命周期,确保在不再需要时及时释放内存,以避免内存泄漏和资源浪费。

变量分类

按照作用域(Scope)和生命周期(Lifetime)的不同,可以将变量进行分类。

全局变量和局部变量是按照作用域进行划分的,全局变量(Global Variables)的作用域是整个程序,局部变量(Local Variables)的作用域是在其所属函数或语句块中。

静态变量和成员变量是按照生命周期进行划分的,静态变量(Static Variables)的声明周期是程序的整个运行期间,成员变量(Member Variables)的生命周期与其所属对象的生命周期相关联。静态变量在函数内部或类内部声明,在多次函数调用之间保持其值的持久性。成员变量是类内部声明的变量,每个类对象都有一份独立的拷贝。

全局变量(Global Variables)、局部变量(Local Variables

按照作用域(Scope)变量可分类为全局变量和局部变量。

全局变量(Global Variables)是在任何函数外部声明的变量,它们具有全局作用域,可以在整个程序中访问。全局变量在程序开始执行时创建,在程序结束时销毁。

而局部变量(Local Variables)是在函数内部声明的变量,它们具有函数作用域或块作用域,只能在其所属的函数或代码块内部访问。局部变量在其所属的函数或代码块执行时创建,在函数调用结束或代码块执行完毕后被销毁。

全局变量和局部变量不同点:

作用域不同:全局变量在整个程序范围内可见,而局部变量仅在其所属的函数或代码块内可见。

存储位置不同:全局变量存储在静态存储区,局部变量通常存储在栈上。

生命周期不同:全局变量在程序运行期间一直存在,而局部变量在其所属的函数或代码块执行期间存在。

需要注意的是,全局变量的使用应谨慎,因为它们对整个程序状态具有持久性影响,并且可能导致命名冲突。为了避免这些问题,应尽量将变量的作用域限制在其必要的范围内,只在需要时使用全局变量。

C++中全局变量、局部变量和变量的作用域的关系

在C++中,全局变量、局部变量和变量的作用域之间存在着一定的关系。以下是它们之间的关系:

全局变量:全局变量(Global Variables)是在任何函数外部声明的变量,具有全局作用域,可以在整个程序中访问。它们在程序开始执行时创建,在程序结束时销毁。全局变量可以被程序中的任何函数使用,包括主函数(main)以及其他自定义函数。全局变量对程序中的所有函数都是可见和可访问的。

局部变量:局部变量(Local Variables)是在函数内部声明的变量,具有函数作用域或块作用域,只能在其所属的函数或代码块内部访问。局部变量在其所属的函数或代码块执行时创建,在函数调用结束或代码块执行完毕后被销毁。局部变量的作用域限定在声明它们的函数或代码块内部,超出该范围就无法访问。

注意事项:

在同一个作用域内,变量名必须是唯一的,否则会引发命名冲突。

当全局变量和局部变量具有相同的名称时,在函数内部访问该名称时,局部变量将优先被使用。

在嵌套的作用域内可以有同名的变量。内层作用域中的变量将覆盖外层作用域中的变量。在内层作用域中,同名的变量将引用内层作用域中的变量。当离开内层作用域时,外层作用域中的变量将再次可见。

在函数内部可以通过作用域解析操作符(::)来访问全局变量,以区分同名的局部变量。

下面示例展示了C++中全局变量和局部变量的使用:

#include <iostream>

// 全局变量
int globalVariable = 10;

void func() {
    // 局部变量
    int localVariable = 5;
    
    // 打印全局变量和局部变量
    std::cout << "全局变量 globalVariable 的值: " << globalVariable << std::endl;
    std::cout << "局部变量 localVariable 的值: " << localVariable << std::endl;
}

int main() {
    func();
    
    // 这里无法访问局部变量 localVariable
    std::cout << "全局变量 globalVariable 的值: " << globalVariable << std::endl;
    
    return 0;
}

输出示例:

全局变量 globalVariable 的值: 10
局部变量 localVariable 的值: 5
全局变量 globalVariable 的值: 10

静态变量(Static Variables)和成员变量(Member Variables

按照生命周期(Lifetime)进行分类变量可分类为静态变量(Static Variables)和成员变量(Member Variables)。

静态变量(Static Variables)是在函数内部或类内部声明的变量,具有静态存储持续性。这意味着它们在每次函数调用或类实例化时都保持其值,并且在多次调用间不会被重新初始化。

在 C++ 中,使用 static 关键字可以声明静态变量。静态变量与普通变量的区别在于其生命周期和作用域。普通变量在函数执行完毕后被销毁,而静态变量在整个程序运行期间都存在,只会被销毁一次。静态变量的作用域也不同,静态变量在声明它的文件中全局可见,但在其他文件中不可见。而普通变量的作用域仅限于声明它的作用域内。

例如:

#include<iostream> 
using namespace std;
void func() {
    static int count = 0;
    count++;
    cout << "Count: " << count << endl;
}

int main() {
    func(); // 输出:Count: 1
    func(); // 输出:Count: 2
    func(); // 输出:Count: 3
    return 0;
}

在上面的例子中,变量count被声明为静态变量,它在每次调用func函数时保持其值,实现了计数的功能。

成员变量(Member Variables)是定义在类中的变量,用于描述类的属性和状态。成员变量可以在整个类中被访问和使用。通常,每个对象拥有自己的一组成员变量,它们的值相互独立。

在C++中,成员变量的定义通常放在类的声明中,并且没有具体的赋值。在类的对象创建时,每个成员变量将被赋予默认值,例如整数类型的成员变量将被赋值为0,字符类型的成员变量将被赋值为空字符。

例如:

示例中,Rectangle 类有两个成员变量 width 和 height。我们创建了一个名为 rect 的对象,并使用点运算符(.)设置成员变量的值。然后通过点运算符访问成员变量的值,并计算矩形的面积。

需要注意的是,成员变量的访问权限可以根据类中的访问说明符进行控制。例如,如果将成员变量定义为 private,则只能在类的内部访问和修改这些变量的值。

在类内部声明的静态变量是类静态成员变量

在类内部声明的静态成员变量在每个类对象之间都有一份独立的拷贝,它在所有该类对象之间共享。例如:

#include<iostream> 
using namespace std;

class MyClass {
public:
    static int count; // 类静态成员变量声明
    
    MyClass() {
        count++;
    }
};

int MyClass::count = 0; // 在类外部初始化静态成员变量

int main() {
    MyClass obj1;
    cout << "Count: " << obj1.count << endl; // 输出:Count: 1
    
    MyClass obj2;
    cout << "Count: " << obj2.count << endl; // 输出:Count: 2
    
    return 0;
}

在上面的例子中,静态成员变量count被声明为类MyClass的一部分,因此它与类的每个对象实例相独立。每次创建一个新的MyClass对象时,count的值增加一次。通过类名和作用域解析操作符::访问静态成员变量。

在C++中,上面介绍的这些常见的变量类型之外,还有:

形参变量(Parameter Variables):函数的参数也是一种变量,在函数内部使用,参数变量的作用域仅限于函数内部,离开函数后其分配的存储空间会自动被释放——形参在函数退出后被销毁。

外部变量(extern variable):外部变量是指在一个文件中声明,在其他文件中定义和使用的变量。在 C++ 中,使用 extern 关键字声明外部变量。

等等。

小结

C++ 中的作用域指的是变量、函数或其他标识符的可见和可访问的范围。

变量作用域是指变量的生命周期和可见性,也就是变量在程序中的哪些部分可以使用。

全局变量和局部变量按照作用域(Scope)进行分类,全局变量的作用域是整个程序,局部变量的作用域是在其所属函数或语句块中。

静态变量和成员变量按照生命周期(Lifetime)进行分类,静态变量的生命周期是整个程序运行期间,成员变量的生命周期与所属对象相关联。

猜你喜欢

转载自blog.csdn.net/cnds123/article/details/132234436