变量作用域 和 多文件编程

变量作用域

概念

C++ 中的一个 变量 或 常量 在程序中都有一定的作用范围,称之为作用域。

变量定义

作用:给一段指定的内存空间起名,方便操作这段内存,相当于被某块内存起了个别名。

typedef声明

typedef是在计算机编程语言中用来为复杂的声明定义简单的别名, 它与宏定义有些差异。它本身是一种存储类的关键字,与auto、 extern、mutable、static、register等关键字不能出现在同一个表达式中

  1. typedef 可以声明各种类型名,但不能用来定义变量。
  2. 用typedef只是对已经存在的类型增加一个类型名,不能创造新的类型
  3. 当在不同源文件中用到同一类型数据(尤其是像数组、指针、结构体、共用体等类型数据)时,常用 typedef 声明一些数据类型,以提高编程效率
  4. typedef 有利于程序的通用与移植。有时程序会依赖于硬件特性,用 typedef 便于移植

局部变量

在 函数 内部声明/定义的变量叫局部变量,局部变量的作用域仅限 于函数内部。同时,在函数内部定义的变量,函数的 参数 和 返回 值,if 和 for 结构内部使用的变量等都是局部变量。

当存在全局变量和局部变量同名的时候,在函数内,局部变量会覆 盖全局变量。

使用 {} 可以限制变量的作用

全局变量

在函数外部声明/定义的变量叫全局变量,C++ 全局变量作用域在整个文件都有效。

静态变量

静态存储区的变量是在程序刚开始的时候就会完成初始化,也是整 个程序生命周期的唯一一次初始化。

静态存储区中一般存储两种变量:static 变量和全局变量。

static变量在函数内定义局部变量的时候,作用域只在其函数内, 但是生存周期为整个源程序。即只可以在定义该变量的函数内进行 使用,但是退出该函数后,该变量一直存在,但不可以进行使用。

c++存储类

存储类用于定义C++程序中变量和函数的生命周期和可见性

有五种类型的存储类,可以在C++程序中使用

  1. 自动(Automatic)
  2. 寄存器(Register)
  3. 静态(Static)
  4. 外部(External)
  5. 可变(Mutable)

image-20230107093240140

auto 自动存储类

auto是所有局部变量的默认存储类。

auto关键字自动应用于所有局部变量。

{

auto int v1;

float v2 = 99.1;

}

上面的例子定义了两个具有相同存储类的变量,auto只能在函数中使用。

static 静态存储

静态变量只初始化一次,直到程序结束。

它保留可在多个函数之间调用的值。

静态变量由编译器提供的一个默认值:0。

register 注册存储类

寄存器变量在寄存器中分配存储器而不是RAM。 其大小与寄存器 大小相同。 它比其他变量具有更快的访问速度。

建议仅使用寄存器变量进行快速访问!

ex:在计数器中。

register int count=0;

注意:不能得到寄存器变量的地址

extern 外部存储类

extern变量对所有程序都可见。

如果两个或多个文件共享相同的变量或函数,则使用它。

extern int v1 = 0;

多文件编程

多文件编程概念

为了方便分工或后期的维护,分散代码应遵循一个基本原则:实现相同功能的代码应存储在一个文件中。

C++ 代码文件根据后缀名的不同,大致可以分为如下几类:

.h:头文件

.hpp:头文件,header plus plus 的缩写,混杂着 .h 的声明 .cpp 的定义,OpenCV 采用

.cpp:源文件,windows

.cc:源文件,Unix/Linux

又或者是有一天,你写出了很牛的功能代码,出于版权和保密考虑, 大多是已经编译好的二进制文件,可能仅包含 .h 文件

// 1.student.h
void printInfo();

// 2.student.cpp
#include "sudent.h"
//printInfo 定义

// 3.main.cpp
#include "student.h"
int main(){
// ... }

步骤

  1. 在资源管理器-解决方案中,找到头文件
  2. 在头文件文件夹上右键->添加->新建项
  3. 选择头文件(.h)->在名称处起名***.h
  4. 点击添加
  5. 编写代码 (注意:要包含***.h文件)

#include “.h” 即可使用*

include <> 和 #include ""的区别

  1. #include <>

#include <>引用的是编译器的类库路径里面的头文件。

一般用于引用标准头文件,如stdio.h,string.h等

  1. #include " ”

#include ""引用的是项目相对路径中的头文件

一般用于引用自定义的头文件。

如果使用#include “” ,首先会在当前项目所在文件夹下寻找是否有对应的头文件,如果没有, 还是会到编译器自带头文件目录中查找。

例如,使用#include “stdio.h” ,如果项目中不包含stdio.h这个头文件,则还是会定位到标准头 文件中查找stdio.h这个文件。

防止头文件重复包含

使用宏定义避免重复引入

#ifndef _NAME_H
#define _NAME_H
//头文件内容
#endif

_NAME_H是宏的名称

注意:设置的宏名必须是独一无二的,不要和项目中其他宏的名称相同

当程序中第一次 #include 该文件时,由于 _NAME_H 尚未定义,所以会定义 _NAME_H 并执行 “头文件内容”部分的代码;当发生多次 #include 时,因为前面已经定义了 _NAME_H,所以不 会再重复执行“头文件内容”部分的代码。

可移植性强。

使用#pragma once避免重复引

#pragma once //放在文件开头位置

#ifndef 是通过定义独一无二的宏来避免重复引入的,意味着每次引入头文件都要进行识别,所以效率不高。 但考虑到 C 和 C++ 都支持宏定义,所以项目中使用 #ifndef 规避可能出现的“头文件重复引入”问题,不会影响 项目的可移植性

和 ifndef 相比

#pragma once 不涉及宏定义,当编译器遇到它时就会立刻知道当前文件只引入一次,所以效率很高。

但值得一提的是,并不是每个版本的编译器都能识别 #pragma once 指令,老版本的编译器有些是不支持该指令(执行时会发出警告, 但编译会继续进行),即 #pragma once 指令的兼容性不是很好

除此之外,#pragma once 只能作用于某个具体的文件,而无法像 #ifndef 那样仅作用于指定的一段代码

目前,几乎所有常见的编译器都支持 #pragma once 指令,甚至于 V S 2017 新建头文件时就会自带该指令。可以这么说,在 C/C++ 中, #pragma once 是一个非标准但却逐渐被很多编译器支持的指令。

用_Pragma操作符

_Pragma(“once”)

//放在文件开头位置

C99 标准中新增加了一个和 #pragma 指令类似的 _Pragma 操作符,其可以看做是 #pragma 的增强版,不仅可以实现 #pragma 所有的功能,更重要的是, _Pragma 还能和宏搭配使用。

考虑到编译效率和可移植性,#pragma once 和 #ifndef 经常被结合 使用来避免头文件被重复引入

#pragma once 
#ifndef _NAME_H
#define _NAME_H
//头文件内容
#endif

当编译器可以识别 #pragma once 时,则整个文件仅被编译一次!

如果编译器不识别 #pragma once 指令,此时仍有 #ifndef在发挥作用

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tian Meng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值