「C++系列」C++ 变量作用域

news2025/1/12 21:06:43

文章目录

  • 一、C++ 变量作用域
  • 二、局部变量
  • 三、全局变量
  • 四、类作用域
  • 五、相关链接

在这里插入图片描述

一、C++ 变量作用域

在C++中,变量的作用域(Scope)指的是变量在程序中可以被访问的区域。作用域由花括号{}定义,这些花括号可以出现在函数体、控制结构(如if语句、循环语句)或任何块级结构中。根据变量的定义位置,C++中的变量可以分为几种不同的作用域类型:

  1. 全局作用域(Global Scope)
  • 在所有函数外部定义的变量具有全局作用域。
  • 这些变量在程序的整个执行期间都是可见的,并且可以从程序的任何位置访问。
  • 尽量避免使用全局变量,因为它们可能导致代码难以理解和维护。
  1. 局部作用域(Local Scope)
  • 在函数内部或块(由花括号{}包围的代码块)内部定义的变量具有局部作用域。
  • 这些变量仅在其定义的函数或块内部可见和可访问。
  • 一旦离开定义它们的函数或块,这些变量将不再存在。
  1. 命名空间作用域(Namespace Scope)
  • 在命名空间中定义的变量具有命名空间作用域。
  • 这些变量在该命名空间内是可见的,但可以通过使用命名空间的名称来从外部访问。
  • 命名空间用于组织代码,避免命名冲突。
  1. 类作用域(Class Scope)
  • 在类内部定义的变量(成员变量)具有类作用域。
  • 这些变量只能通过类的对象或类的成员函数来访问。
  • 根据访问权限(public、protected、private),这些变量的可见性可以进一步限制。
  1. 块作用域(Block Scope)
  • 实际上,局部作用域和块作用域可以视为同一概念的不同表述。
  • 任何由花括号{}包围的代码块内部定义的变量都具有块作用域。
  1. 函数原型作用域(Function Prototype Scope)
  • 在函数原型中声明的参数名仅在函数原型内部具有作用域。
  • 这些名称在函数定义或函数体内部是不可见的。

理解变量的作用域对于编写高效、可维护的C++代码至关重要。正确地使用作用域可以避免命名冲突,提高代码的可读性和可维护性。同时,也要注意作用域的生命周期,确保在适当的时候释放不再需要的资源,以避免内存泄漏等问题。

二、局部变量

C++中的局部变量是在函数内部或代码块(由花括号{}包围的区域)中定义的变量。这些变量仅在定义它们的函数或代码块内部可见和可访问,一旦离开该作用域,这些变量就会被销毁,其占用的内存也会被释放(对于自动存储期的局部变量而言)。

下面案例,展示了局部变量的使用:

#include <iostream>

// 函数声明
void printNumbers();

int main() {
    // main函数中的局部变量
    int mainVar = 10;
    std::cout << "在main函数中,mainVar的值为: " << mainVar << std::endl;

    // 调用函数
    printNumbers();

    // 注意:这里不能访问printNumbers函数中的局部变量,因为它们的作用域仅限于该函数内部

    return 0;
}

// 函数定义
void printNumbers() {
    // printNumbers函数中的局部变量
    int num1 = 5, num2 = 10;

    // 另一个代码块(if语句内部)
    if (num1 < num2) {
        // 这个变量仅在if语句的代码块内部有效
        int temp = num1 + num2;
        std::cout << "num1 + num2 = " << temp << std::endl;

        // 尝试在if语句外部访问temp会导致编译错误
        // std::cout << "temp的值为: " << temp << std::endl; // 错误:temp在此处不可见
    }

    // 在这里可以访问num1和num2,但不能访问temp
    std::cout << "num1的值为: " << num1 << ", num2的值为: " << num2 << std::endl;

    // 函数结束,num1、num2和temp(如果它能在函数外部访问的话,但实际上不能)都将被销毁
}

在这个例子中,mainVarmain函数中的局部变量,而num1num2tempprintNumbers函数中的局部变量。temp变量是在if语句的代码块中定义的,因此它仅在该代码块内部可见和可访问。一旦执行离开if语句的代码块,temp变量就会被销毁,其占用的内存也会被释放。

注意,虽然局部变量在函数或代码块结束时会被销毁,但它们的销毁并不直接等同于内存的立即释放。内存的释放依赖于C++的运行时环境(如栈的弹出操作),这通常发生在函数返回或代码块执行完毕后。然而,对于动态分配的内存(使用new操作符分配的内存),则需要在适当的时候使用delete操作符来显式释放,以避免内存泄漏。局部变量通常不涉及动态内存分配,因此不需要程序员显式地释放它们占用的内存。

三、全局变量

在C++中,全局变量是在所有函数外部定义的变量,这意味着它们在程序的整个执行期间都是可见的,并且可以从程序的任何位置访问。但是,过度使用全局变量可能会导致代码难以理解和维护,因为它们可以在程序的任何地方被修改,从而引入难以追踪的错误。

下面案例,展示了全局变量的使用:

#include <iostream>

// 全局变量定义
int globalVar = 100;

// 函数声明
void modifyGlobalVar();
void printGlobalVar();

int main() {
    // 在main函数中访问全局变量
    std::cout << "在main函数中,全局变量globalVar的初始值为: " << globalVar << std::endl;

    // 调用函数修改全局变量
    modifyGlobalVar();

    // 再次在main函数中访问全局变量,查看其值是否已改变
    std::cout << "在modifyGlobalVar函数执行后,全局变量globalVar的值为: " << globalVar << std::endl;

    // 调用另一个函数打印全局变量的值
    printGlobalVar();

    return 0;
}

// 函数定义:修改全局变量的值
void modifyGlobalVar() {
    // 直接访问并修改全局变量
    globalVar = 200;
    std::cout << "在modifyGlobalVar函数中,全局变量globalVar的值已被修改为: " << globalVar << std::endl;
}

// 函数定义:打印全局变量的值
void printGlobalVar() {
    // 访问并打印全局变量的值
    std::cout << "在printGlobalVar函数中,全局变量globalVar的值为: " << globalVar << std::endl;
}

在这个例子中,globalVar是一个全局变量,它在main函数、modifyGlobalVar函数和printGlobalVar函数中都是可见的。modifyGlobalVar函数修改了globalVar的值,然后在main函数中通过两次打印来展示这个变化。printGlobalVar函数也打印了globalVar的值,以进一步证明全局变量的全局可见性。

然而,尽管全局变量在某些情况下可能很方便,但通常建议尽可能避免使用它们,而是使用函数参数、返回值或类成员变量来传递和存储数据。这样可以提高代码的可读性、可维护性和可重用性。

四、类作用域

在C++中,类作用域(Class Scope)是指类内部定义的成员(包括成员变量和成员函数)的作用域。这些成员只能通过类的对象或者类的成员函数来访问(取决于成员的访问权限:public、protected或private)。

下面是一个C++类作用域的案例代码:

#include <iostream>
#include <string>

// 定义一个名为Person的类
class Person {
private: // 私有成员,只能通过成员函数访问
    std::string name; // 私有成员变量
    int age; // 另一个私有成员变量

public: // 公有成员函数,可以在类外部通过对象访问
    // 构造函数,用于初始化对象
    Person(std::string n, int a) : name(n), age(a) {}

    // 成员函数,用于设置名字
    void setName(std::string n) {
        name = n;
    }

    // 成员函数,用于获取名字
    std::string getName() const {
        return name;
    }

    // 成员函数,用于设置年龄
    void setAge(int a) {
        if (a >= 0) {
            age = a;
        }
    }

    // 成员函数,用于获取年龄
    int getAge() const {
        return age;
    }

    // 成员函数,用于打印个人信息
    void printInfo() const {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }
};

int main() {
    // 创建Person类的对象
    Person person1("Alice", 30);

    // 通过公有成员函数访问私有成员
    std::cout << "Initial info of person1: ";
    person1.printInfo();

    // 修改对象的属性
    person1.setName("Bob");
    person1.setAge(25);

    // 再次打印以查看修改后的信息
    std::cout << "Modified info of person1: ";
    person1.printInfo();

    // 创建另一个Person类的对象
    Person person2;
    // 注意:这里person2使用了默认构造函数(如果未定义,则编译器会生成一个),因此其成员变量可能未被初始化
    // 最好为所有类定义至少一个构造函数来初始化成员变量

    return 0;
}

在这个例子中,Person类有两个私有成员变量nameage,以及多个公有成员函数来访问和修改这些私有成员变量的值。注意,私有成员变量nameage不能直接从类外部访问,只能通过类的公有成员函数(如getNamesetNamegetAgesetAge)来访问和修改它们的值。

此外,Person类还定义了一个构造函数,用于在创建Person类的对象时初始化nameage成员变量。构造函数是一个特殊的成员函数,它在创建类的对象时自动调用。

最后,main函数中创建了两个Person类的对象person1person2,并通过调用Person类的公有成员函数来访问和修改这些对象的私有成员变量的值。注意,由于person2在创建时没有提供初始化参数,并且我们没有为Person类定义默认构造函数来初始化其成员变量,因此person2的成员变量可能处于未定义状态(这取决于编译器如何处理未初始化的局部变量)。在实际应用中,最好为所有类定义至少一个构造函数来初始化其成员变量。

五、相关链接

  1. Visual Studio Code下载地址
  2. Sublime Text下载地址
  3. 「C++系列」C++简介、应用领域
  4. 「C++系列」C++ 基本语法
  5. 「C++系列」C++ 数据类型
  6. 「C++系列」C++ 变量类型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1895956.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[C++]——同步异步日志系统(2)

同步异步日志系统 一、 不定参函数1.1 不定参宏函数的使用1.2 C 语言中不定参函数的使用1.3 C不定参数使用 二、设计模式2.1 单列模式2.2 工厂模式2.3 建造者模式2.4 代理模式 在我们开发同步异步日志系统之前&#xff0c;需要了解一些相关的技术知识。 一、 不定参函数 在初学…

WPF UI 界面布局 魔术棒 文字笔记识别 技能提升 布局功能扩展与自定义 继承Panel的对象,测量与排列 系列七

应用开发第一步 功能分类&#xff1a;页面上的功能区域划分。。。。需求分析 业务逻辑 数据流 功能模块 UI/UX 编码 测试 发布 功能开发与布局 不用显式的方式设定元素的尺寸 不使用屏幕坐标来指定位置 Grid 功能最强大&#xff0c;布局最灵活的容器…

视频融合共享平台LntonCVS视频监控汇聚平台工业视频监控系统

LntonCVS是一款功能强大、灵活部署的安防视频监控平台&#xff0c;具备广泛的扩展性和视频能力。它支持多种主流标准协议&#xff0c;如国标GB28181、RTSP/Onvif、RTMP&#xff0c;同时还能兼容厂家的私有协议和SDK&#xff0c;如海康Ehome、海大宇等。除了传统的安防监控功能外…

阿里巴巴Arthas分析调优JVM实战及常量池详解

目录 一、阿里巴巴Arthas详解 Arthas使用场景 Arthas命令 Arthas使用 二、GC日志详解 如何分析GC日志 CMS G1 GC日志分析工具 三、JVM参数汇总查看命令 四、Class常量池与运行时常量池 字面量 符号引用 五、字符串常量池 字符串常量池的设计思想 三种字符串操作…

Linux 账号安全管理及应用

一、账号安全控制 1.系统账号清理 1.1 将非登录用户设置为无法登录 usermod -s /etc/nologin pkm #将名为pkm 用户的shell设为/sbin/nologin 用户 pkm 将无法登录 1.2 锁定长期不使用的账号 usermod -L 用户名 #锁定用户账号密码 usermod -U …

TCP报文校验和(checksum)计算

一. 原理 将TCP相关内容&#xff08;TCP伪头部TCP头部TCP内容&#xff09;转换成16比特的字符&#xff0c;然后进行累加&#xff0c;最后结果进行取反。TCP伪头部是固定的&#xff0c;下文有相关代码展示。 二. 源码 源码 #include <stdio.h> #include <stdlib.h&…

在 VS Code 中自动化 Xcode 项目编译和调试

在 VS Code 中自动化 Xcode 项目编译和调试 在日常的开发工作中&#xff0c;Xcode 是 macOS、iOS、watchOS 和 tvOS 应用程序开发的主要工具。为了提高工作效率&#xff0c;许多开发者选择在 Visual Studio Code (VS Code) 中编辑代码&#xff0c;并希望能够直接从 VS Code 启…

人工智能系列-numpy(一)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” Numpy是python语言的一个拓展程序库&#xff0c;支持大量的维度数组与矩阵计算&#xff0c;此外也针对数组运算提供大量的数学函数库 NumPy支持的数据类型比Python内置的类型要…

系统架构设计师教程(清华第2版)<第1章 绪论>解读

系统架构设计师教程 第一章 绪论 1.1 系统架构概述1.1.1 系统架构的定义及发展历程1.1.2 软件架构的常用分类及建模方法1.1.3 软件架构的应用场景1.1.4 软件架构的发展未来1.2 系统架构设计师概述1.2.1 架构设计师的定义、职责和任务1.2.2 架构设计师应具备的专业素质1.3 如何成…

计算机的错误计算(二十一)

摘要 两个不相等数相减&#xff0c;差为0&#xff1a; ? 在计算机的错误计算&#xff08;十九&#xff09;中&#xff0c;高中生小明发现本应为0的算式结果不为0. 今天他又发现对本不为0的算式&#xff0c;计算机的输出为0. 在 Python 中计算 &#xff1a; 则输出为0. 若用 C…

ArmPiPro-环境变量

V0.0 2024-07-04 V0.1 加入开发环境和PI4关于ROS的环境变量的对比 1.我们可以用env | grep ROS来查看Pi4中的ROS环境变量 如下图所示&#xff0c;不理解的&#xff0c;抛给AI快速了解一下。 2.ArmPiPro安装的ROS是ROS1-melodic 3.在开发时&#xff0c;需要在笔记本电脑上开一…

天环公益原创开发进度网站源码带后台免费分享

天环公益计划首发原创开发进度网站源码带后台免费分享 后台地址是&#xff1a;admin.php 后台没有账号密码 这个没有数据库 有能力的可以自己改 天环公益原创开发进度网站 带后台

how to use Xcode

Xcode IDE概览 Xcode 页面主要分为以下四个部分&#xff1a; 工具栏&#xff08;ToolBar area&#xff09;&#xff1a;主要负责程序运行调试&#xff0c;编辑器功能区域的显示 / 隐藏&#xff1b;编辑区&#xff08;Editor area&#xff09;&#xff1a;代码编写区域&#xf…

MYSQL8.0环境部署

创建用户 groupadd mysql useradd -g mysql mysql 删除原来的包 # rpm -qa|grep mysql # rpm -qa|grep mari mariadb-libs-5.5.68-1.el7.x86_64 # rpm -e --nodeps mariadb-libs-5.5.68-1.el7.x86_64 解压 cd /usr/local & mkdir mysql cd mysql # cp mysql-8…

记一次 .NET某网络边缘计算系统 卡死分析

一&#xff1a;背景 1. 讲故事 早就听说过有什么 网络边缘计算&#xff0c;这次还真给遇到了&#xff0c;有点意思&#xff0c;问了下 chatgpt 这是干嘛的 ? 网络边缘计算是一种计算模型&#xff0c;它将计算能力和数据存储位置从传统的集中式数据中心向网络边缘的用户设备、…

【设计模式】观察者模式(定义 | 特点 | Demo入门讲解)

文章目录 定义结构Demo | 代码Subject目标类Observer抽象观察者观察者1 | CPU监听器观察者2 | 内存监听器客户端 | Client 优点适合场景 定义 所谓观察者模式就是你是被观察的那个对象&#xff0c;你爸爸妈妈就是观察者&#xff0c;一天24h盯着你&#xff0c;一旦你不听话&…

前端引用vue/element/echarts资源等引用方法Blob下载HTML

前端引用下载vue/element/echarts资源等引用方法 功能需求 需求是在HTML页面中集成Vue.js、Element Plus&#xff08;Element UI的Vue 3版本&#xff09;、ECharts等前端资源&#xff0c;使用Blob下载HTML。 解决方案概述 直接访问线上CDN地址&#xff1a;简单直接&#xff0c…

实训学习错误总结2

1、 "timestamp": "2024-07-04T08:43:07.15400:00", "status": 405, "error": "Method Not Allowed", "path": "/wuzi/insert" 简单的来说就是使用的方法与注释不匹配。 规定的是&#xff1a;Get&a…

图DFS遍历

DFS遍历图 伪代码 俩函数。 判断图有几个连通分支&#xff1f;就是图的遍历&#xff0c;dfs完了就给他 #include <iostream> #include <cstdlib> #include <bits/stdc.h> #include <vector> using namespace std; const int N102; int n,m,temp1,te…

从开源小白到新晋 committer:主动尝试,心无旁骛,收获满满!

又一位清华同学加入&#xff01; 2024 年 6 月 12 日&#xff0c;经 Apache IoTDB 社区投票&#xff0c;杨蔡胤成为 Apache IoTDB committer。之前从未参加过开源社区贡献的他&#xff0c;为什么选择了 IoTDB&#xff0c;又为什么能够坚持到现在&#xff0c;有什么样的收获与成…