C++新经典07--auto、头文件防卫、引用与常量

news2024/9/29 23:33:24

auto的使用

严格来讲,在C语言中,如果某个函数中需要用到一些局部变量,那么局部变量都会集中定义在函数开头,而在C++中不必遵循这样的规则,随时用随时定义即可。当然,作用域一般就是从定义的地方开始到该函数结束为止。当然,也有例外,例如如果在一个循环中定义的变量就只在循环内有效,在一个{}包着的语句块中定义的变量就只能在该语句块内有效。典型的如for(int i=0;i<100;i++){…},i的作用域就仅仅限制在for循环体内。传统编码方式中,可以使用“=”在定义变量的时候进行初始化。代码如下:

int abc = 5;

在C++新标准中,可以使用“{}”在定义变量的时候进行初始化。代码如下:

int abc {5};

所以,针对刚才的for语句,可以换一种写法。代码如下:
在这里插入图片描述
在看到了C++新标准中“{}”的用法后,需要额外说明的是,在“{}”之前还可以增加一个“=”号。如下代码:

在这里插入图片描述
在上面的“{}”用法中,只涉及一个数据,因为只有一个变量来接收数据。实际上,如果定义一个数组,那么是可以在“{}”中包含一组数据的。代码如下:
在这里插入图片描述
建议在学习的时候,把这些新标准的写法单独整理和记录一下,新标准中引入“{}”这种给变量初值的方法也是有一些考虑和好处的。例如下面这行语句:
在这里插入图片描述
上面这行代码是可以编译通过的,但执行起来后会发现,实际上abc因为是int类型,所以3.5的小数部分会被截断,结果是abc的值等于3。那下面这种C++新标准语法呢?
在这里插入图片描述
上面这行代码根本无法编译通过,直接报语法错,这样做的好处是不会使数据被误截断,进一步保证所写的代码的健壮性。
再看一例,用“()”也可以对变量进行初始化:
在这里插入图片描述

auto关键字简介

auto关键字其实在C++98中就已经有了,只是那时候这个关键字没什么作用,但是到了C++11中,auto被赋予了全新的含义——变量的自动类型推断。

auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型(这表明在声明变量的同时也要给变量初始值)。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。

换句话说,在定义一个变量的时候,如果变量类型能够由系统推断出来,就不需要显示指定类型。看看如下范例:
在这里插入图片描述

有些类型名很长,如后面要学习到的泛型,那么,使用auto就能避免书写很长的类型名。

头文件防卫式声明

C/C++头文件中有关于#ifndef、#define、#endif的用法。
通过下面的语言描述创建一个范例:
(1)头文件head.h中有如下定义:

int g_globalh1 = 8;

(2)头文件head2.h中有如下定义:

int g_globalh2 = 5;

(3)在主源文件(MyProject.cpp)中需要用这两个全局变量,代码如下:

#include "head.h"
#include "head2.h"
int main()	//主函数
{
	cout <g_globalh1 <endl;	//8
	cout <g_globalh2 <endl;	//15
}

执行上面这段代码,目前为止并没有什么问题。
(4)随着项目的增大,需要定义更多复杂的数据类型,假如现在因为一些原因需要在头文件head2.h中包含头文件head.h,于是头文件head2.h内容修改如下:

#include "head.h"
int g_globalh2 = 5;

此时编译,出现重定义错误。这是因为在源文件MyProject.cpp文件中有如下内容:

#include "head.h"
int g_globalh2 = 5;

如果上面这两行代码都展开,则结果如下:
在这里插入图片描述

显然globalh1被定义了两次,因此编译的时候提示出现重定义错误。

这非常让人头疼,因为保不准哪个头文件就#include了其他头文件,也保不准哪个.cpp源文件无意中就#include两次同一个头文件,上面这种是间接通过head2.h重复#include了head.h,那直接重复#include也是不可以的。例如如下代码,系统编译时也会报错:

在这里插入图片描述

既然重复#include的问题时有发生,无法避免,那么如何解决这个问题呢?

这就要从.h头文件本身入手,通过使用#ifndef、#define、#endif解决这个问题。首先,改造头文件head.h。改造后的内容如下:

#ifndef __HEAD__
#define __HEAD__
int g_globalh1 = 8;
#endif

接着,改造头文件head2.h。改造后的内容如下:

#ifndef __HEAD2__
#define __HEAD2__
#include "head.h"
int g_globalh2 = 5;
#endif

有一点必须说明:每一个.h头文件的#ifndef后面定义的名字都不一样,不可以重名。
如此修改后再次编译,不难发现,编译通过并能成功执行,奥妙在哪里?就在于通过使用#ifndef、#define、#endif的组合,避免了.h头文件中的内容被多次#include。例如当head.h第一次被#include到MyProject.cpp中时,#ifndef HEAD条件成立,因此下面两行代码都被#include到MyProject.cpp中:
在这里插入图片描述
但是假如第二次head.h被#include到MyProject.cpp中时,#ifndef HEAD条件就不成立了(因为#define HEAD代码行的存在),这样,上面两行内容就不会再次被#include到MyProject.cpp中,从而避免了重定义等错误的发生。

所以要求读者在书写.h头文件的时候,要习惯性地在文件头部增加#ifndef、#define语句行,在文件末尾增加#endif语句行。出现在.h头文件中的这三行代码,被习惯性地称为“头文件防卫式声明”。

引用

引用是为变量起的另外一个名字(别名),一般用“&”符号(以往看到过该符号,但含义与这里并不相同)表示。之后,该引用和原变量名代表的变量看成是同一个变量。所以,在理解时要理解成:定义引用并不额外占用内存。或者也可以理解成,引用和原变量占用的是同一块内存。
看看如下范例:
在这里插入图片描述
定义引用类型的时候必须进行初始化,不然给哪个变量起别名呢?看看如下范例,找找代码行中的错误:
在这里插入图片描述

看看如下范例,注意比较,看看“&”作为引用和作为取地址符时的使用区别:
在这里插入图片描述
再看一个比较完整的范例——引用作为函数形参:

#include <iostream>
using namespace std;
void func(int &ta,int &tb)   	//形参类型都是引用类型(整型引用) @
{
	ta = 4;        //改ta和tb值直接影响到main()中的a和b
	tb = 5;
}
int main()        //主函数
{
	int a = 13;
	int b = 14;
	func(a, b);
	cout << a <<" "<< b<< std::endl;	//4 5
	return 0;
}

常量

常量就是不变的量。前面讲解的常量一般都是具体的数值,如10、23.5等。

1.const关键字

该关键字有很多作用,但这里不准备多介绍,主要是先熟悉一下。const表示不变的意思。定义变量时,可以在前面增加const关键字,一旦增加该关键字,该变量的值就不可以发生改变。看看如下范例:
在这里插入图片描述

2.constexpr关键字

这是C++11引入的关键字,也代表一个常量的概念,意思是在编译的时候求值,所以能够提升运行时的性能。编译阶段就知道值也会带来其他好处,例如更利于做一些系统优化工作等。看看如下范例:

constexpr int var1 = 1;
constexpr int var2 = 11 * func1(12);

上面代码用到了func1函数,那func1函数要怎样写呢?这里必须注意,因为var2是常量,初始化时调用了func1函数,所以func1也得定义成constexpr。代码如下:

constexpr int func1(int abc)
{
	abc = 16;
	int a3 =5;
	return abc * a3;
}

但是,在书写func1函数时必须小心,其中的代码尽可能简单。而且,某些代码出现在func1函数中还会导致编译无法通过。例如,在func1函数中定义一个未初始化的变量就会导致编译出错,必须在定义的时候初始化:

int unvar;	//编译时会引发错误,必须在定义的时候初始化

再如,如果下面的for循环语句出现在func1函数中,那么for循环中的printf语句也同样会引发编译错误,

for (int i = 0;i < 100; i++)
{
	//这句printf也会导致编译不过。不是这个函数有问题,而是constexpr关键字的问题
	printf("good");
}

还可以进行一些尝试:

int k = 3;
constexpr int var= 11 * func1(k);	//编译错误,不可以用变量k作为参数
int k2 = func1(k);		//用变量k调用constexpr函数不会有问题,
					//此时该函数相当于普通函数,结果当然也是在执行期间产生

可以看到,加了constexpr修饰的函数不但能用在常量表达式中,也能用在常规的函数调用中。

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

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

相关文章

人工智能引领图文扫描新趋势

1. 背景和影响 近日&#xff0c;中国大学生服务外包创新创业大赛决赛在江南大学圆满落幕。为满足现代服务产业企业的现实需求&#xff0c;本次竞赛内容设计充分聚焦企业发展中所面临的技术、管理等现实问题&#xff0c;与产业的结合度更紧密&#xff0c;智能文字识别技术是大赛…

6款必备的办公软件,个个好用到爆,让你电脑成为真正利器

在现代办公环境中&#xff0c;电脑已经成为我们必不可少的工作工具。而要发挥电脑的最大作用&#xff0c;就需要借助一些优秀的办公软件。下面&#xff0c;就来介绍五款必备的办公软件&#xff0c;它们个个好用到爆&#xff0c;让你的电脑成为真正的利器&#xff01; 文件快速搜…

性能优越的静电监控系统是怎样的?

随着社会的发展&#xff0c;各种监控系统应运而生。静电监控系统是其中之一。它具有优异的性能和稳定性&#xff0c;能够有效地检测和发现静电。 1&#xff1a;静电监控系统的优势 静电监控系统是一种先进的自动化控制系统&#xff0c;它能够有效地检测和控制企业运营中的各种…

【Java从0到1学习】10 Java常用类汇总

1. System类 System类对读者来说并不陌生&#xff0c;因为在之前所学知识中&#xff0c;需要打印结果时&#xff0c;使用的都是“System.out.println();”语句&#xff0c;这句代码中就使用了System类。System类定义了一些与系统相关的属性和方法&#xff0c;它所提供的属性和…

条码通讯配置

由Leuze&#xff08;劳易测&#xff09; LSIS 222 M5M-R1/MA208i系统组成 连接说明及器件明细&#xff1a; 打开条码调试软件BPS Configuration tool对M208i进行ip 和端口号进行配置&#xff0c;条码选择作为客户端&#xff0c;输入ip和端口号&#xff0c;选择串口通讯波特…

基于java校园二手交易平台-lw-源码

二手交易平台论文 源码 文章目录 前言一、主要技术javaMysql数据库JSP技术B/S结构 二、系统设计三、功能截图总结 前言 随着社会的不断发展与进步&#xff0c;人们对信息科学化的认识越来越深入&#xff0c;管理工作的重要性逐渐被认识到。科学化的管理能够实现信息存储的准确…

【O2O领域】Axure外卖订餐骑手端APP原型图,外卖众包配送原型设计图

作品概况 页面数量&#xff1a;共 110 页 兼容软件&#xff1a;Axure RP 9/10&#xff0c;不支持低版本 应用领域&#xff1a;外卖配送、生鲜配送 作品申明&#xff1a;页面内容仅用于功能演示&#xff0c;无实际功能 作品特色 本品为外卖订餐骑手端APP原型设计图&#x…

nodejs+vue+elementui实验室课程预约管理系统 t1g73

通过前面的功能分析可以将实验室课程管理系统的功能分为管理员、学生和教师三个部分&#xff0c;系统的主要功能包括首页、个人中心、教师管理、学生管理、教师课表管理、实验室信息管理、实验课程管理、预约记录管理、实验成绩管理、设备信息管理、借用记录管理、归还记录管理…

解决云服务连接时长过短,不到一会儿自动断开

我们在使用xshell或者FinalShell连接云服务器操作时&#xff0c;总是十分钟就自动断开&#xff0c;很烦&#xff0c; 下面我们设置一下&#xff0c;让他可以使用很长时间&#xff08;需要有一定的linux命令的基础&#xff09; cd /etc/ssh 进入到ssh这个目录&#xff0c;查看…

node使用高版本的oracledb导致连接oracle的Error: NJS-138异常

异常信息如下 Error: NJS-138: connections to this database server version are not supported by node-oracledb in Thin mode 我的oracle版本是11g&#xff0c;之前的使用正常&#xff0c;今天却报错了&#xff0c;显示不支持thin模式&#xff0c;后面回退版本就可以了。

Lnton羚通算法算力云平台【PyTorch】教程:torch.nn.Softsign

torch.nn.Softsign 原型 CLASS torch.nn.Softsign() 图 代码 import torch import torch.nn as nnm nn.Softsign() input torch.randn(4) output m(input)print("input: ", input) print("output: ", output)# input: tensor([ 0.0046, -0.4135, -2…

SAP 开发创建后台job(SM36)

T-code&#xff08;SE38&#xff09;写一个程序&#xff1a;取数并保存到透明表&#xff0c;假如程序名叫&#xff08;ZPRG_TEST001&#xff09;; T-code&#xff08;SM36&#xff09;定义一个后台作业&#xff0c;设置执行频率为每天晚上12点&#xff0c;设置步骤如下&#x…

简单介绍 CPU 的工作原理

内部架构 CPU 的根本任务就是执行指令&#xff0c;对计算机来说最终都是一串由 0 和 1 组成的序列。CPU 从逻辑上可以划分成 3 个模块&#xff0c;分别是控制单元、运算单元和存储单元 。其内部架构如下&#xff1a; 【1】控制单元 控制单元是整个CPU的指挥控制中心&#xff…

【力扣】77. 组合 <回溯、回溯剪枝>

目录 【力扣】77. 组合题解回溯回溯法三步剪枝优化 【力扣】77. 组合 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按任何顺序返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2]…

x86 Linux系统下构建交叉编译工具(3)

接前一篇文章&#xff1a;x86 Linux系统下构建交叉编译工具&#xff08;2&#xff09; 本文参考以下文章&#xff1a; 建立交叉编译器 for arm &#xff08;binutils-2.17 gcc-3.4.6 glibc-2.3.6&#xff09; 特此致谢&#xff01; 上一回构建了binutils的交叉环境&#xff0…

实例040 限制窗体大小

实例说明 Windows窗体是可以随意改变大小的&#xff0c;然而对于一些要求严格的窗体&#xff0c;开发人员不希望用户随意的改变其大小&#xff0c;例如&#xff0c;定位准确的地图和游戏软件等。遇到这种情况必须对窗口的大小进行一些限制。本例设计一个限制了大小的窗体&#…

幼儿园托幼机构管理系统 微信小程序

托幼机构管理系统微信小程序从功能、数据流程、可行性、运行环境进行需求分析。对托幼机构管理系统微信小程序的数据库、功能进行了详细设计&#xff0c;分析了主要界面设计和相关组件设计&#xff0c;托幼机构管理系统微信小程序的具体实现进行了介绍。从数据库中获取数据、向…

小航助学GESP_C++一级模拟测试卷第4套(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSD…

qt中窗口的布局

qt中窗口的布局 常用的窗口布局方式使用拖拽控件的方式调用窗口布局使用Widget控件完成窗口布局布局中嵌套布局demo&#xff08;制作登录页面&#xff09; 如果不使用窗口布局&#xff0c;会带来的后果&#xff1a; 控件可能显示不出来不能按照期望的大小显示不能跟随窗口进行…

时间戳转换成浏览器对应的UTC时间、时间戳根据对应的时区转换成对应的UTC时间

/*** 毫秒级时间戳转成 浏览器时间对应的 UTC时间**/toBrowserTime(timestamp) {//输入毫秒级 timestamp1692579702028if (!timestamp) {return null} else {let date moment(timestamp).format()let browserTime date.replace(/-/g, "/").replace(/T/g, " &q…