【C++】C++入门(下)——有C语言基础的C++学习

news2024/11/13 15:13:55

C++入门(下)

  • 一、引用
    • 1.引用的概念
    • 2.引用的定义
    • 3.引用特性
    • 4.常引用
    • 5.使用场景
      • 做参数
      • 做返回值
    • 6.引用的作用
    • 7.引用与指针的区别
  • 二、内联函数
    • 1.概念
    • 2.特性
  • 三、auto关键字(C++11)
    • 1.简介
    • 2.auto的使用细则
      • auto与指针和引用结合起来使用
      • 在同一行定义多个变量
    • 3.auto不能推导的场景
  • 四、基于范围的for循环(C++11)
    • 1.使用方法
    • 2.使用条件
  • C++98中的指针空值

一、引用

1.引用的概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间
比如:李逵,在家称为"铁牛",江湖上人称"黑旋风"。
李逵
图片来源自网络

2.引用的定义

类型& 引用变量名(或者对象名)=引用实体;
如:

int a = 10;//被引用的实体
int& pa = a;//引用的定义

注意:引用类型必须和引用实体是同种类型的。

3.引用特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体
void TestRef()
{
	int a = 10;
	// int& ra; // 该条语句编译时会出错
	int& ra = a;
	int& rra = a;
	printf("%p %p %p\n", &a, &ra, &rra);
}

4.常引用

在引用的定义前面加上const关键字,构成常引用。常引用经常在函数参数中使用,它可以提高程序的效率,同时又保证了数据的安全性,因为常引用所引用的对象是只读的,不能被修改。
如:

void TestConstRef()
{
	const int a = 10;
	//int& ra = a; // 该语句编译时会出错,a为常量
	const int& ra = a;
	// int& b = 10; // 该语句编译时会出错,b为常量
	const int& b = 10;
	double d = 12.34;
	//int& rd = d; // 该语句编译时会出错,类型不同
	const int& rd = d;
}

5.使用场景

做参数

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

做返回值

int& Count()
{
	static int n = 0;
	n++;
	// ...
	return n;
}

注意:做返回值时不能将函数中的临时变量返回。即如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回

6.引用的作用

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。
使用引用就可以很好的避免这个问题,将效率大大提高。

7.引用与指针的区别

(1) 在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。

int main()
{
	int a = 10;
	int& ra = a;
	cout<<"&a = "<<&a<<endl;
	cout<<"&ra = "<<&ra<<endl;
	return 0;
}

运行结果
(2) 在底层实现上实际是有空间的,因为引用是按照指针方式来实现的

int main()
{
	int a = 10;
	int& ra = a;
	ra = 20;
	int* pa = &a;
	*pa = 20;
	return 0;
}

我们来看下引用和指针的汇编代码对比:
汇编对比
引用和指针的不同点:

  1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
  2. 引用在定义时必须初始化,指针没有要求
  3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  4. 没有NULL引用,但有NULL指针
  5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32
    位平台下占4个字节)
  6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  7. 有多级指针,但是没有多级引用
  8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  9. 引用比指针使用起来相对更安全

二、内联函数

1.概念

inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率

2.特性

(1)inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
(2)inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为《C++prime》第五版关于inline的建议:
内联的建议
(3)inline不能声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

【 面试题】
宏的优缺点?
优点:

  1. 增强代码的复用性。
  2. 提高性能。

缺点:

  1. 不方便调试宏。(因为预编译阶段进行了替换)
  2. 导致代码可读性差,可维护性差,容易误用。
  3. 没有类型安全的检查 。

C++有哪些技术替代宏?

  1. 常量定义 换用const enum
  2. 短小函数定义 换用内联函数

三、auto关键字(C++11)

1.简介

C++11中,标准委员会赋予了auto全新的含义,即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。
如:

int TestAuto()
{
	return 10;
}
int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	//auto e; 无法通过编译,使用auto定义变量时必须对其进行初始化
	return 0;
}

运行结果
注意:
使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

2.auto的使用细则

auto与指针和引用结合起来使用

用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&。

int main()
{
	int x = 10;
	auto a = &x;
	auto* b = &x;
	auto& c = x;
	cout << typeid(a).name() << endl;
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	*a = 20;
	*b = 30;
	c = 40;
	return 0;
}

运行结果

在同一行定义多个变量

当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

void TestAuto()
{
	auto a = 1, b = 2;
	auto c = 3, d = 4.0; // 该行代码会编译失败,因为c和d的初始化表达式类型不同
}

3.auto不能推导的场景

(1) auto不能作为函数的参数
(2) auto不能直接用来声明数组
(3) 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
(4) auto在实际中最常见的优势用法就是跟以后会讲到的C++11提供的新式for循环,还有lambda表达式等进行配合使用

四、基于范围的for循环(C++11)

1.使用方法

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

void TestFor()
{
	int array[] = { 1, 2, 3, 4, 5 };
	for(auto& e : array)
		e *= 2;
	for(auto e : array)
		cout << e << " ";
	return 0;
}

运行结果
注意:与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

2.使用条件

for循环迭代的范围必须是确定的
对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。
注意:以下代码就有问题,因为for的范围不确定

void TestFor(int array[])
{
	for(auto& e : array)
	cout<< e <<endl;
}

C++98中的指针空值

我们在C语言中对指针置空时常用NULL,
而NULL实际是一个宏,在传统的C头文件(stddef.h)中,可以看到如下代码:

#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif

这里NULL有可能定义为字面常量0,或者被定义为无类型指针(void*)的常量,不管怎样都会造成一些麻烦。
所以,建议在C++中使用nullptr

  1. 在使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。
  2. 在C++11中,sizeof(nullptr) 与 sizeof((void*)0)所占的字节数相同。
    3.** 为了提高代码的健壮性,在后续表示指针空值时建议最好使用nullptr。**

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

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

相关文章

python appiumn 自动化测试 入门

资源下载 链接&#xff1a;https://pan.baidu.com/s/1zl1yXYna73RAL-V0PQ9xHA 提取码&#xff1a;syjg 安装JDK 不详细说了 配置Android SDK 新建 ANDROID_HOME配置对应的SDK路径 新增PATH 安装python库 pip install Appium-Python-Client报如图错误的话可以使用 pytho…

搭建FTP

第一步&#xff1a;按【Win R】快捷键打开运行对话框&#xff0c;输入“optionalfeatures”后&#xff0c;按回车键 第二步&#xff1a;从“启用或关闭Windows功能”弹窗中找到Internet Information Services(或者中文版Internet信息服务)并打开&#xff0c;配置IIS并点击确…

单片机语音芯片开发要解决的问题

在单片机语音芯片开发过程中&#xff0c;可能会遇到多种问题&#xff0c;这些问题可能来自于技术层面&#xff0c;也可能来自于芯片本身的设计和应用层面。下面让我们具体从芯片的功耗、语音识别的准度、芯片的尺寸和芯片的可靠性四个方面开展讨论。 1.芯片的功耗问题 首先&a…

motionlayout的简单使用

MotionLayout 什么是motionLayout&#xff1f; MotionLayout 是 Android 中的一个强大工具&#xff0c;用于创建复杂的布局动画和过渡效果。它是 ConstraintLayout 的一个子类&#xff0c;继承了 ConstraintLayout 的布局功能&#xff0c;同时添加了动画和过渡的支持。Motion…

Java字节码指令集概述及分类详解

Java全能学习面试指南&#xff1a;https://javaxiaobear.cn 1、字节码指令集与解析概述 Java字节码对于虚拟机&#xff0c;就好像汇编语言对于计算机&#xff0c;属于基本执行指令。 Java 虚拟机的指令由一个字节长度的、代表着某种特定操作含义的数字&#xff08;称为操作码&a…

Redis并发问题解决方案

目录 前言 1.分布式锁 1.基于单个节点 2.基于多个节点 3.watch(乐观锁) 2.原子操作 1.单命令操作 2.Lua 脚本(多命令操作) 3.事务 1.执行步骤 2.错误处理 3.崩溃处理 总结 前言 在多个客户端并发访问Redis的时候&#xff0c;虽然Redis是单线程执行指令&#xff…

Banana Pi [BPi-R3-Mini] 回顾和主线 ImmortalWrt 固件支持

BananaPi BPi-R3 Mini 采用 MediaTek 830&#xff08;4 个 A53&#xff0c;最高 2.0 GHz&#xff09;&#xff0c;具有 2 个 2.5 GbE、AX4200 2.4G/5G 无线和 USB 2.0 端口。它还具有两个 M.2 连接器&#xff0c;可用于 NVMe SSD 和 5G 模块&#xff08;板上包含 Nano SIM 插槽…

绝地求生:PGC 2023 赛事直播期间最高可获:2000万G-Coins,你还不来吗?

今年PGC直播期间将有最高2000万G-Coin掉落&#xff0c;究竟花落谁家咱们拭目以待 公告原文&#xff1a;Watch PGC 2023 Live And Earn G-Coins! 如何赚取高额G-Coin&#xff1f; Throughout the PGC 2023, an astounding 20,000,000 G-Coins will be up for grabs as part of …

常见树种(贵州省):013桉树、米槠、栲类

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、桉树 …

京东数据分析(京东大数据):2023年10月京东手机行业品牌销售排行榜

鲸参谋监测的京东平台10月份手机市场销售数据已出炉&#xff01; 根据鲸参谋平台的数据显示&#xff0c;今年10月份&#xff0c;京东平台手机行业的销量约340万&#xff0c;环比增长约11%&#xff0c;同比则下滑约2%&#xff1b;销售额为108亿&#xff0c;环比增长约17%&#x…

c#数据库:vs2022 加入mysql数据源

网上有VS2019连接MySQL数据库的&#xff0c;那么VS2022&#xff0c;VS2023如果和连接到mysql数据库呢&#xff0c;这里总结一下我的经历&#xff1a; 1、首先下载ODBC驱动安装包 当前下载地址&#xff1a;https://dev.mysql.com/downloads/connector/odbc/ 2、ODBC安装 下载完…

小程序可拖拽按钮

你有没有遇到过在页面中有一个固定在某个位置的按钮&#xff0c;永远的挡住了你想要看的区域&#xff1f; 在小程序的列表页面中&#xff0c;常常会有一个提报的入口固定在右下角&#xff0c;如果这个按钮不可拖动的话&#xff0c;可能会挡住下面的事件&#xff0c;让用户操作起…

PyTorch包

进入PyTorch的官网&#xff1a; pytorch GitHub 点击GitHub&#xff1a; 进入PyTorch的主目录&#xff1a; 进入Vision reference&#xff1a; detection&#xff1a; 这就是我们在训练过程中会使用到的文件了&#xff1a;

如何使用springboot服务端接口公网远程调试——实现HTTP服务监听

&#x1f308;个人主页&#xff1a;聆风吟 &#x1f525;系列专栏&#xff1a;网络奇遇记、数据结构、算法模板 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 &#x1f4cb;前言一. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 二. 内网穿透…

机器学习笔记 - 复杂任务的CNN组合

基础CNN架构可通过多种方式进行组合和扩展,从而解决更多、更复杂的任务。 1. 分类和定位 在分类和定位任务中,你不仅需要说出在图像中找到的物体的类别,而且还需指出物体显现在图像中的边界框坐标。这类任务假设在图像中只有一个物体实例。 这个任务可通过在典型的分类网络…

多数据库使用django-apscheduler时,migrate后并不能生成django_apscheduler_djangojob表的问题

先说一下django-apscheduler定时器的使用过程&#xff1a; django-apscheduler基本使用 1.安装django-apscheduler代码如下&#xff08;示例&#xff09;&#xff1a; pip install django-apscheduler 2.配置settings.py的INSTALLED_APPS代码如下&#xff08;示例&#xff09…

B033-Servlet交互 JSP

目录 ServletServlet的三大职责跳转&#xff1a;请求转发和重定向请求转发重定向汇总请求转发与重定向的区别用请求转发和重定向完善登录 JSP第一个JSP概述注释设置创建JSP文件默认字符编码集 JSP的java代码书写JSP的原理三大指令九大内置对象改造动态web工程进行示例内置对象名…

关于elementui和ant design vue无法禁止浏览器自动填充问题

以and design vue 为例&#xff1a; 图标用来显隐账号密码 html&#xff1a; <a-form-model-item label"账号密码:" prop"password"><a-input v-if"passwordTab" ref"passwordInput" v-model"form.password" typ…

如何进行MySQL的主从复制(MySQL5.7)

背景&#xff1a;在一些Web服务器开发中&#xff0c;系统用户在进行数据访问时&#xff0c;基本都是直接操作数据库MySQL进行访问&#xff0c;而这种情况下&#xff0c;若只有一台MySQL服务器&#xff0c;可能会存在如下问题 数据的读和写的所有压力都会由一台数据库独…

利用STM32CubeMX解读时钟树

1&#xff0c;低速时钟 LSE是外部晶振作时钟源&#xff0c;主要提供给实时时钟模块&#xff0c;所以一般采用32.768KHz。LSI是由内部RC振荡器产生&#xff0c;也主要提供给实时时钟模块&#xff0c;频率大约为40KHz。(LSE和LSI)只是提供给芯片中的RTC(实时时钟)及IWDG(独立看门…