C++自学记录(变量)

2023-11-05

目录

变量

变量定义

初始值

赋值≠初始化 

列表初始化

默认初始化 

变量声明和定义的关系

 关键概念:静态类型

 标识符

变量命名规范:

名字的作用域 

        嵌套的作用域


​​​​​​​

变量

变量提供一个具名的、可供程序操作的储存空间。

变量中的数据类型决定着变量所占内存空间的大小和布局方式,该空间能存储的值的范围,以及变量能参与的运算。

“变量”和“对象”一般可以互换使用。

对象:是指一块能储存数据并具有某种类型的内存空间。

不同的人使用对象的场景不同:

  1. 一些人仅在为类有关的场景下使用“对象”这个词。
  2. 另一些人则已把命名的对象和未命名的对象区分开,把名了命的对象叫做变量。
  3. 还有一些人把对象和值区分开来,其中对象指能被程序修改的数据,而值(value)指只读的数据。

变量定义

变量定义的基本形式是:首先是类型说明符(type specifier),随后紧跟由一个或多个变量名组成的列表,其中变量名以逗号分隔,最后以分号结束。

int sum = 0 , value;      //sum、value和units_sold都是int

列表中的每个变量名的类型都由类型说明符指定。

int x;
double y;    //其中的int和double都是类型说明符

定义时还可以为一个或多个变量赋初值。

int sum = 0 , value = 0;

 其中string是一种库类型,表示一个可变长的字符序列。

std::string book("0-201-78345-X");    //book通过一个string字面值初始化

book的定义用到了库类型std::string,string是一种表示可变长字符序列的数据类型,上面使用的是一种初始化string的方法,直接一种是把字面值拷贝给string对象。

初始值

当对象在创建时获得了一个特定的值,我们说这个对象被初始化(initialized)。

初始化时的值可以是任意复杂的表达式。

当一次定义了两个或多个变量时,对象的名字随着定义也就马上可以使用了。

因此在同一条定义语句中,可以用先定义的变量值去初始化后定义的其他变量;

double price = 109.99 , discount = price * 0.16;
//正确:price先被定义并被赋值,随后被用于初始化discount。

double salePrice = applyDiscount(price , discount);
//正确:调用函数applyDiscount , 然后用函数返回值初始化salePrice。

赋值≠初始化 

在C++语言中,初始化和赋值是两个完全不同的操作。

初始化:创建变量时赋予其一个初始值。

赋值:把对象的当前值擦除,而以一个新值来替代。

列表初始化

在C++中有几种不同初始化的方式,以下列出四种初始化的方式:

int units_sold = 0;
int units_sold = {0};
int units_sold{0};
int units_sold(0);

⚠️第三种的初始化的方式,作为C++11新标准的一部分,用来花括号来初始化变量得到了全面应用。

        用花括号的初始化的形式被称为列表初始化(list initializaton)。现在,无论是初始化对象还是某些时候为对象新赋值,都可以使用这样一组由花括号括起来的初始值了。

        当用于内置类型的变量时,这样的初始化形式有一个重要特点:如果我们使用列表初始化且初始值存在丢失信息的风险,则编译器将报错。

long double id = 3.141592;
int a(id) , b = {id};    //错误:转换未执行,因为存在丢失信息的危险。
int c(id) , d = id;      //正确:转换执行,且确实丢失了部分值

        使用long double 的值初始化int变量时可能丢失数据,所以编译器拒绝了a和b的初始化请求。其中,至少id的小数部分会丢失掉,而且int也可能存不下id的整数部分。(这里指的是普遍现象,并不是指上述例子)。

        平常我们可能不会故意用long double转换int , 但是我们经常在不经意之间做出这种初始化。

默认初始化 

如果定义变量时没有指定初值,则变量被默认初始化(default initialized),此时变量被赋予了“默认值”。

 默认值由什么决定:

  1.  变量类型
  2. 定义变量的位置

         如果是内置类型的变量未被显示初始化,其值由定义的位置决定。

        定义于任何函数体之外的变量被初始化为0.

一种例外情况:定义在函数体内部的内置类型变量将不被初始化(uninitialized),一个未被初始化的内置类型变量的值是未定义的,如果试图拷贝或以其他形式访问此类值将引发错误。

        每个类各自决定其初始化对象的方式。而且,是否允许不经初始化就定义对象也由类来决定。 

        绝大多数类都支持无须显示初始化而定义对象的方式,这样的类提供了一个合格的默认值。

 string类规定如果没有指定初值则生成一个空串:

std::string empty;    //empty非显式地初始化为一个空串
Sales_item item;      //被默认初始化的Sales_item对象

         一些类要求每个对象都显式初始化,此时如果创建了一个该类的对象而未被对其做明确的初始化操作,将引发错误。

变量声明和定义的关系

为了允许把程序拆分成多个逻辑部分来编写,C++语言支持分离式编译(separate compilation)​​​​​​​机制,该机制允许将程序分割成若干个文件,每个文件可被独立编译。 

 为了支持分离式编译,C++语言将声明和定义区分开。

声明(declaration) :使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含对那个名字的声明。 

定义(definition):    负责创建与名字关联的实体。

变量声明规定了变量的类型和名字,这一点上与定义是相同的。但是除此之外,定义还申请存储空间,也可能会为变量赋一个初始值。

 如果想声明一个变量而非定义它,就在变量名前添加 关键字extern,而且不要显式地初始化变量:

extern int i;    //声明I而非定义i
int j;           //声明并定义j

任何包含了显式初始化的声明即成为定义。我们能给由extern关键字标记的变量赋一个初始值,但是这么做也就抵消了extern的作用。

extern语句如果包含初始值就不再是声明,而变成了定义:

extern double pi = 3.1415;    //定义

在函数体内部,如果试图初始化一个由extern关键字标记的变量,将引发错误。

变量能且只能被定义一次,但是可以被多次声明 

 变量的定义必须出现在且只能出现在一个文件中,而其他用到该变量的文件必须对其进行声明,却绝对不能重复定义。 

tip:建议初始化每一个内置类型的变量。虽然并非必须这么做,但如果我们不能确保初始化后程序安全,那么这么做不失为一种简单可靠的方法。 

 关键概念:静态类型

C++是一种静态类型(statically typed)语言,其含义是在编译阶段检查类型。其中,检查类型的过程称为类型检查(type checkig) 

程序越复杂,静态类型检查越有助于发现问题。然而,前提是编译器必须知道每一个实体对象的类型,这就要求我们在使用某个变量之前必须声明其类型

 标识符

C++的标识符(identifier)由字母、数字和下画线组成,其中必须以字符或下画线开头。标识符的长度没有限制,但是对大小字母敏感:

//定义4个不同的int变量
int somename,someName,SomeName , SOMENAME;

用户自定义标识符要求:

  1. 用户自定义的标识符中不能连续出现两个下画线
  2. 也不能以下画线紧连大写字母开头
  3.  定义在函数体外的标识符不能以下画线开头 

变量命名规范:

  • 标识符要能体现实际含义​​​​​​​
  • 变量名一般用小写字母,如:index,不要使用Index或INDEX
  • 用户自定义的类名一般以大写字母开头,如Sales_item
  • 如果标识符由多个单词组成,则单词间应有明显区分,如:student_loan 或 studentLoan,不要使用studentloan

名字的作用域 

        不论是在程序的什么位置,使用到的每个名字都会指向一个特定的实体:变量、函数、类型等。然而,用一个名字如果出现在程序的不同位置,也可能指向的是不同实体。

        作用域(scope)是程序的一部分,在其中名字有其特定的含义。C++语言中大多数作用域都以花括号分隔。

名字的有效区域始于名字的声明语句,以声明语句所在的作用域末端为结束。

        名字main定义于所有花括号之外,它和其他大多数定义在函数体之外的名字一样拥有全局作用域(global scope)。

        而定义于main内的变量仅作用于main的开头花括号至末端花括号内,出了main函数所在的块就无法访问了,因此说此变量拥有块作用域(block scope)。

        嵌套的作用域

        作用域能彼此包含,被包含(或者说被嵌套)的作用域称为内层作用域(inner scope),包含着别的作用域的作用域被称为外层作用域(outer)

        作用域中一旦声明了某个名字,它所嵌套着的所有作用域中都能访问这个名字。同时,允许在内层作用域中重新定义外层作用域已有的名字:

#include <iostream>
//该程序仅用于说明:函数内部不宜定义与全局变量同名的新变量
int main(){
    int reused = 42;    //reused拥有全局作用域
    //输出#1:使用全局变量reused;输出42 0
    std::cout << reused << "" << unique << std::endl;
    int reused = 0;    //新建局部变量reused,覆盖了全局变量reused
    //输出#2:使用局部变量reused;输出0 0
    std::cout << resued << "" << unique << std::endl;
    //输出#3:显式得访问全局变量reused;输出 42 0
    std::cout << ::reused << "" << unique << std::endl;
    return 0;
} 

此处需要注意的是:输出#3使用作用域操作符来覆盖默认的作用域规则,因为全局作用域本身并没有名字,所以当作用域操作符的左侧为空时,向全局作用域发出请求获取作用域操作符右侧名字对应的变量。结果是,第三条输出语句使用全局变量reused,输出42 0。 

 ⚠️:如果函数有可能用到某全局变量,则不宜再定义一个同名的局部变量。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++自学记录(变量) 的相关文章

  • VLC 媒体播放器有 C# 界面吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 是否可以使用 C 控制台应用程序中的包装器从 VLC 播放中当前播放的文件中读取曲目统计信息 时间 标
  • 如何从字符串中提取子字符串直到遇到第二个空格?

    我有一个像这样的字符串 o1 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 1232 5467 如何仅提取 o1 1232 5467 要提取的字符数并不总是相同 因此 我只想提取直到遇到
  • 格式说明符%02x

    我有一个简单的程序 include
  • 是否需要销毁运算符删除的形式才能真正销毁对象?

    C 20 添加了破坏形式operator delete区别于std destroying delete t范围 它导致delete表达式在调用之前不再销毁对象operator delete 目的是在显式调用对象的析构函数和释放内存之前 允许
  • 如何在 C# 中将 Json 转换为对象

    我想将 Json 转换为 C 中的对象 这里的 Json 是 值 e920ce0f e3f5 4c6f 8e3d d2fbc51990e4 如何使用 Object 问题看似愚蠢 但其实并不那么愚蠢 我没有简单的 Json 我有 IEnume
  • Selenium - C# - Webdriver - 无法找到元素

    在 C 中使用 selenium 我试图打开浏览器 导航到 Google 并找到文本搜索字段 我尝试下面的 IWebDriver driver new InternetExplorerDriver C driver Navigate GoT
  • 混合模型优先和代码优先

    我们使用模型优先方法创建了一个 Web 应用程序 一名新开发人员进入该项目 并使用代码优先方法 使用数据库文件 创建了一个新的自定义模型 这 这是代码第一个数据库上下文 namespace WVITDB DAL public class D
  • if constexpr 中的 not-constexpr 变量 – clang 与 GCC

    struct A constexpr operator bool const return true int main auto f auto v if constexpr v A a f a clang 6 接受该代码 GCC 8 拒绝它
  • Unity手游触摸动作不扎实

    我的代码中有一种 错误 我只是找不到它发生的原因以及如何修复它 我是统一的初学者 甚至是统一的手机游戏的初学者 我使用触摸让玩家从一侧移动到另一侧 但问题是我希望玩家在手指从一侧滑动到另一侧时能够平滑移动 但我的代码还会将玩家移动到您点击的
  • Linux 上的 RTLD_LOCAL 和dynamic_cast

    我们有一个由应用程序中的一些共享库构成的插件 我们需要在应用程序运行时更新它 出于性能原因 我们在卸载旧插件之前加载并开始使用新插件 并且只有当所有线程都使用旧插件完成后 我们才卸载它 由于新插件和旧插件的库具有相同的符号 我们dlopen
  • 如何在 Javascript 中连接 C# ActiveX 事件处理程序

    我尝试使用几个代码片段将 ActiveX 对象与 Javascript 事件处理程序挂钩 我无法确定为什么事件处理程序没有被调用 带有项目的 Github 存储库 https github com JesseKPhillips Csharp
  • 让网络摄像头在 OpenCV 中工作

    我正在尝试让我的网络摄像头在 Windows 7 64 位中的 OpenCV 版本 2 2 中捕获视频 但是 我遇到了一些困难 OpenCV 附带的示例二进制文件都无法检测到我的网络摄像头 最近我发现这篇文章表明答案在于重新编译一个文件 o
  • 对于 C# Express 用户来说,有哪些好的工具可以识别可能重复的代码? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 也可以看看 有什么工具可以检查重复的 VB NET 代码吗 https stackoverflow c
  • .NET 和 Mono 之间的开发差异

    我正在研究 Mono 和 NET C 将来当项目开发时我们需要在 Linux 服务器上运行代码 此时我一直在研究 ASP NET MVC 和 Mono 我运行 Ubuntu 发行版 想要开发 Web 应用程序 其他一些开发人员使用 Wind
  • C++ 指针引用混淆

    struct leaf int data leaf l leaf r struct leaf p void tree findparent int n int found leaf parent 这是 BST 的一段代码 我想问一下 为什么
  • 如何在C#中控制datagridview光标移动

    我希望 datagridview 光标向右移动到下一列 而不是在向单元格输入数据后移动到下一行 我试图通过 dataGridView1 KeyDown 事件捕获键来控制光标 但这并不能阻止光标在将数据输入到单元格后移动到下一行 提前感谢你的
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 在 C# 的 WebAPI 中的 ApiController 上使用“传输编码:分块”提供数据

    我需要服务分块传输使用编码数据API控制器 因为我无权访问HttpContext or the Http请求 我有点不知道在哪里写入响应以及在哪里刷新它 设置如下 public class MyController ApiControlle
  • Streamwriter 覆盖 txt 文件中的文本

    有没有什么方法可以重新打开流写入器而不创建新的写入对象 因为此时 当调用 WriteOdd 时 streamwriter 正在覆盖在它之前调用的 WriteEven public void WriteEven StreamWriter wr
  • 如何在 ASP.NET Core 中注入泛型的依赖关系

    我有以下存储库类 public class TestRepository Repository

随机推荐

  • 基于CC2530的Zstack协议栈的SX1278调试记录

    SX1278Lora模块串口调试记录 串口调试代码 串口获取调试信息 SPI驱动IO口模拟 加深理解用 SX1278的通讯时序 SX1278 SPI通讯间隔要求 SX1278 寄存器设置 实例 实际调试 LORA信道划分建议 关于带宽 只是
  • [Elasticsearch]源码解析:ES如何避免脚本中的危险操作

    一 简述 在我们使用ES进行脚本操作的时候 可以在脚本中使用painless等脚本语言 但我们是否有想过在脚本中进行危险操作类似System exit 0 的时候 ES是怎么规避这种风险的 不废话 上例子 POST trick search
  • (二十八)admin-boot项目之基于MDC的全局日志追踪

    二十八 基于MDC的全局日志追踪 项目地址 https gitee com springzb admin boot 如果觉得不错 给个 star 简介 这是一个基础的企业级基础后端脚手架项目 主要由springboot为基础搭建 后期整合一
  • 服务器怎样创建多台虚拟主机,服务器是如何实现多台虚拟主机

    服务器是如何实现多台虚拟主机 内容精选 换一换 弹性云服务器 Elastic Cloud Server 是一种可随时自动获取 计算能力可弹性伸缩的云服务器 可帮助您打造可靠 安全 灵活 高效的应用环境 确保服务持久稳定运行 提升运维效率 通
  • 调用VSPD的DLL进行二次开发异常解决的解决方法。

    最近在学习 设想做一个实现虚拟串口的C 程序 因为我不会写驱动 于是参考老哥的方法 调用VSPD的DLL开放接口进行实现 从VSPD虚拟COM口安装包解出独立的驱动安装包 虚拟串口开发和EXE程序反解压 http blog csdn net
  • 开机f8修复电脑步骤_只要按一个键,可以修复很多电脑小故障

    经常遇到 客户的电脑开机进不了系统 卡在修复界面 半天没反应 有的开机在检测界面 一直没反应 还有的因为运行的程序太多 开个机要耐着性子 等10多分钟 才能使用电脑 还一直很慢 很卡 要重装系统 又担心很多程序找不到安装程序 只能一直忍 很
  • Python无法打开excel文档解决办法

    问题 无法打开excel文档 解决办法 安装xlrd模块 在cmd命令行下执行 pip install pyexcel xls 如果以上方法无法解决 继续报以下问题 pandas无法打开 xlsx文件 xlrd biffh XLRDErro
  • QQ js_sdk第三方授权登录 自定义登录按钮

    STEP 1 QQ放置页面添加 img src qq png function qqLogin QC Login showPopup 替换APPID和回调页面即可 STEP 2
  • 获取百度翻译内容

    import requests url https fanyi baidu com sug s input 请输入你要翻译的英文单词 dic kw s resp requests post url data dic print resp j
  • 【Unity】常见的角色移动旋转

    在Unity 3D游戏引擎中 可以使用不同的方式对物体进行旋转 以下是几种常见的旋转方式 欧拉角 Euler Angles 欧拉角是一种常用的旋转表示方法 通过绕物体的 X Y 和 Z 轴的旋转角度来描述物体的旋转 在Unity中 可以通过
  • mysql 报错 your password has expired.To log in you must change itusing a client that supports expired

    学习java少不了和数据库打交道 在使用 Navicat 连接 mysql 的时候 出现了这个错误 这表示你设置的密码过期了 这里我们重新设置一下密码即可 1 打开 cmd 窗口 进入 mysql 的 bin 目录下 2 连接mysql m
  • C++游戏制作入门小游戏(迷宫)此篇只适用于新手

    最近有些无聊 于是翻了翻以前的代码 找到了之前第一次编的游戏 想起以前学完C 无从下手的感觉 就把它加了点备注 当做一篇入门教程发出来了 这是用DevC 写的 参考自一位大佬写的贪吃蛇 下面上图 PS 开始界面我现在看来是相当的丑 好吧菜单
  • linux开机自动挂载硬盘命令,linux添加新磁盘分区开机自动挂载(随记)

    1 首先先添加一块新的磁盘 ps 虚拟机测试 2 添加好一个磁盘后 10GB 执行reboot命令 重启系统生效 reboot 3 执行fidsk l 则出现了新添加的磁盘 为sdb 4 执行分区命令 fdisk dev sdb n 为新建
  • 软件测试--bug的等级划分

    bug的严重级别 致命的软件缺陷 Blocker 一级bug 1 造成系统或应用程序崩溃 死机 数据丢失 系统挂起 如代码错误 死循环 数据库发生死锁 一直锁在一个地方不解锁 2 与数据库连接错误或数据通讯错误 未考虑异常操作 功能错误等
  • Markdown 技能树(4):链接

    Markdown 技能树 4 链接 Markdown 支持两种形式的链接语法 行内和参考两种形式 不管是哪一种 链接的文字都是用 方括号 来标记 行内形式链接 行内形式的链接是在方块括号后面接括号并插入网址链接即可 如果你还想要加上链接的
  • Visual Studio 2005集成开发环境图解

    摘要 本文探讨其中的一些功能 并且阐述开发人员如何使用它们以更快 更准确地编写代码 正文 Microsoft Visual Studio 2005 包含许多对开发环境新的增强 创新和提高 其目的在于使 Visual Basic NET 开发
  • 基于R语言3组以上倾向评分逆概率加权(IPTW)

    基于 PS 倾向评分 的IPTW 法首先由 osenbaum作为一种以模型为基础的直接标准化法提出 属于边际结构模型 简单来说 就是把许多协变量和混杂因素打包成一个概率并进行加权 这样的话 我只用计算它的权重就可以了 方便了许多 那么 如何
  • ARTS 挑战打卡的第9天 --- 如何知道一个数是否为2的若干次幂(Algorithm)

    前言 1 今天看到一个有意思的问题 如何判断一个数字是否为2的若干次幂 这个问题并不难 但是对于我们的C语言功底还是有一点点的考验的 2 希望各位可以先自行思考 实在想不出来再看后面的讲解 提示 C语言的位运算是一个好东西 解析 2的若干次
  • OpenCV(C++)----Mat.type()

    原文地址 https blog csdn net jeffdeen article details 52401526 opencv中Mat存在各种类型 其中mat有一个type 的函数可以返回该Mat的类型 类型表示了矩阵中元素的类型以及矩
  • C++自学记录(变量)

    目录 变量 变量定义 初始值 赋值 初始化 列表初始化 默认初始化 变量声明和定义的关系 关键概念 静态类型 标识符 变量命名规范 名字的作用域 嵌套的作用域 变量 变量提供一个具名的 可供程序操作的储存空间 变量中的数据类型决定着变量所占