C++的入门基础(二)

news2024/12/28 6:12:59

目录

  • 引用的概念和定义
  • 引用的特性
  • 引用的使用
  • const引用
  • 指针和引用的关系
  • 引用的实际作用
  • inline
  • nullptr

引用的概念和定义

在语法上引用是给一个变量取别名,和这个变量共用同一块空间,并不会给引用开一块空间。

取别名就是一块空间有多个名字

类型& 引用别名 = 引用对象

int main()
{
	int a = 2;
	int& b = a;
	int& c = a;
	int& d = b;
	//对d取别名,d是b的别名,b是a的别名,d就是a的别名
	b++;

	cout << a << " " << endl;
	cout << b << " " << endl;
	cout << c << " " << endl;
	cout << d << " " << endl;
	// 都是3
    //这就说明了b、c、d都是a的别名,和a共用同一块空间
    
	return 0;
}

引用的特性

1.引用在定义时必须初始化(必须说明是谁的引用)
不说明是谁的引用会报错
2.一个变量可以有多个引用(给别名取别名)
3.引用一旦引用一个实体,再不能引用其他实体
(引用不能改变指向)
1,2点比较简单,现在对第三点说明一下

链表要改变指向要用二级指针
在这里插入图片描述

int main()
{
	int a = 2;

	int& b = a;

	int d = 20;
	
	b = d;
	//这里是赋值不是引用,b不是d的引用
	d++;
	//对d++,a和b并不改变,也说明了b不是d的引用
	//b本来是a的引用,并不能改变成b是d的引用,说明引用不能改变指向
	//后面也会介绍
	
	return 0;
}

在这里插入图片描述

引用的使用

1.引用做传参和做返回值

  • 提高效率
  • 减少拷贝
  • 引用对象改变同时被引用对象改变

比如传值调用,传一个值x,函数中a拿到的是x的一份临时拷贝,而如果用引用就减少了拷贝,提高了效率,因为a是x的别名,就是给本身取了另一个名字

引用对象改变同时被引用对象改变
x++,a也++,你的别名改变了,你本身也会改变

void f1(int& x)
{
 x++;
}

int main()
{
  int a = 0;
  f1(a);

  return 0;
}

引用做返回值
1.int 做返回时返回一个数值,不是直接返回而是会生成一份临时变量再返回,临时变量具有常性,不能被改变

2.int& 做返回时生成一个它的引用,再返回它的引用,数组在堆上出函数不销毁,返回数组中的引用,出函数,改变数组中的某个值
在这里插入图片描述

const引用

注意:权限放大和缩小只存在指针和引用里面
权限不能放大,可以缩小

1.权限放大

const int a = 10;//只读不能写(修改)
int& ra = a;//可以读可以写,权限放大
//正确写法
const int& ra = a;

const int a = 10;//可读不可写
int& ra = a;
//权限放大
const int& ra = a;

const int a = 10;
int rd = a;
//a只读,a的值拷贝进rd中,a一个空间,rd又是一个空间
//rd可读可写,这只是一个拷贝,不是权限放大,
//权限放大只存在指针和引用中

2.权限缩小

int b = 20;
const int& rb = b;

b++;//21,本身权限不缩小
rb++;//不能够改变,只是它的引用权限缩小了

3. 产生临时对象
临时对象具有常性

  • 表达式运算
int a = 10;
const int& rc = 30;
const int& rd = (a+30);

在这里插入图片描述

  • 函数传值返回
int fun(int& a)
{
   a++;
   return a;
}
  • 类型的隐式转换
double d = 2.32;
int i = d;
const int& ri = d;
//double类型转化为int时,会把整型部分放入临时变量中

指针和引用的关系

指针和引用互相不可替代

  • 引用取别名不开空间,指针存一个变量的地址要开空间
  • 引用必须初始化,指针建议初始化,但是语法上不是必须的,指针可以先定义,后面把一个变量的地址放入指针中
  • 引用只能引用一个对象,而不能再引用其他对象,而指针可以不断改变指向
  • 引用可以直接访问指向对象,指针必须解引用才能访问指向对象
  • 引用和指针的sizeof含义不同,引用sizeof是引用类型的大小,指针32位平台下是4个byte,64位平台下是8个byte
  • 引用不容易出现空引用和野引用,指针容易出现空指针和野指针

野引用

int& func()
{
   int a = 0;
   return a;
   //会产生一个别名,返回它的一个别名
   //出函数别名销毁,它的引用销毁
   //再去找它的引用,就是野引用
}

在这里插入图片描述

空引用

int* ptr = NULL:
int& rb = *ptr;
//空引用可以通过编译
rb++;
return 0;
//rb++是对空引用的使用
//对空引用的使用,不会返回0,会返回一个负数,异常返回

表面上是对ptr这个空指针解引用,实际上它的汇编代码并不解引用,而是把ptr的地址放入一个寄存器中,再把寄存器中的地址给rb这个别名,引用的底层是指针
在这里插入图片描述

引用的实际作用

以前交换两个值用传地址的方式 swap(&a,&b);
现在有了引用,可以用swap(a,b);
在主函数中调用函数不用取地址,传参过去的函数定义用引用接收void swap(int& x,int& y),可以不用指针接收,而且不用解引用那么麻烦

但是链表中的二级指针LTNode*& != LTNode&&,指针不能用引用替代掉,C++的引用不能替代指针,因为引用不能改变指针的指向,链表要改变指针的指向用二级指针,LTNode*& == LTNode** ,引用的底层可以理解为指针

引用的实际作用体现在传参里面
使用函数模板,T可以是任意类型

template<class T>
void func(const T& val)
{
  //...
  const 对象
  常量->具有常性
  临时变量->具有常性
  普通变量->可以权限缩小
}

inline

用inline修饰的函数叫内联函数,C++在调用的地方直接展开内联函数,就不需要建立栈桢了,这样可以提高效率

  • C++的inline为了替代C语言的宏函数而设计出来的,宏函数也不建立栈桢,#define 定义的宏函数是一个宏,直接展开
  • 你的代码过大,不会帮你展开,比如递归层次太深,会造成可执行程序变大,内存占用变大,编译器会帮你展开代码短小重复的代码,比如swap交换两个数的值的代码
  • inline不建议声明和定义分离到两个文件,分离会导致链接错误,因为inline展开,函数定义文件的地址会消失,导致找不到函数定义,只有声明,所以定义和声明应该在同一个文件,在调用的地方展开会直接执行
  • vs下默认不展开内联函数,找到项目属性做以下设置
    在这里插入图片描述
    在这里插入图片描述
//内联函数
inline int Add(int x,int y)
{
  int ret = x + y;
  return ret;
}

未展开内联函数
call跳转地址,建立栈桢
在这里插入图片描述
展开内联函数
不跳转,直接在调用的地方展开函数逻辑
在这里插入图片描述

nullptr

nullptr是关键字
nullptr是C++中的空指针,专门用来表示空指针,nullptr只能隐式类型的转换成其他类型的指针形式不能转化成其他类型,比如int

C语言中的 ((void*)0)可以隐式类型转为int和int或其他类型,C++用这套在传参中也是不确定的,会传整型又会传指针
C++的NULL是0,传参中,一个函数的参数是int,另一个函数的参数是int
,那么会执行第一个函数,C++中的NULL指针类型又是整型0,这样比较模糊,所以空指针用nullptr表示,nullptr也是0,但它只有指针形式

void func(int* a)
{}//1
void func(int a)
{}//2
int main()
{
  func(0);//2
  func(NULL);//2
  func((void*)0);//会隐式类型转化,int或int*,不确定走哪个
  //这样说C++走不了空指针了,所以定义一个nullptr表式空指针
  return 0;
}
#define NULL 0  C++
#define NULL ((void*)0) C

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

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

相关文章

vue3+ECharts实现可视化中国地图

目录 版本问题解决 中国地图实现 版本问题解决 目前echarts的最新版本为5.5.1 echarts在4.9.0版本以后移除了中国地图&#xff0c;所以如果的你的版本高于4.9.0就需要手动导入中国地图。版本低于或者等于4.9.0则不需要导入。 这里我分享一种导入方法&#xff1a; 1.将项目的…

前端JS特效第34波:jQuery支持拖拽图片上传的图片批量上传插件

jQuery支持拖拽图片上传的图片批量上传插件&#xff0c;先来看看效果&#xff1a; 部分核心的代码如下&#xff1a; <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <title>jQuery支持拖拽图片上传的图片批…

J027_递归算法

一、求n的阶乘 n的阶乘&#xff1a;1*2*3*4*...*n package com.itheima.d01_file;public class DiguiTest1 {public static void main(String[] args) {//求n的阶乘System.out.println(f(3));System.out.println(f(4));System.out.println(f(5));}private static int f(int n…

[激光原理与应用-111]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 15 - 常见缺陷与波形特征

目录 前言&#xff1a;激光焊接时的光谱特征 可见光 反射光 红外热辐射光 总结 一、动力电池 - 模组 - BusBar焊接 1.1 概述 1.2 没有缺陷波形&#xff1a;一条焊缝 1.3 保护气缺失 1. 可见光 2. 反射光 3. 红外光 综合分析 1.4 功率衰减 1. 可见光 2. 反射光 …

捷配生产总结-PCB上器件布局不好对SMTDIP的影响

在电子制造领域&#xff0c;PCB&#xff08;印刷电路板&#xff09;的设计至关重要&#xff0c;其中器件的布局更是影响着整个生产流程的效率和质量。特别是对于 SMT&#xff08;表面贴装技术&#xff09;和 DIP&#xff08;双列直插式封装&#xff09;这两种常见的组装工艺&am…

STM32之七:SPI通信

目录 1.SPI通信简介 1.1 主从模式 1.2 4根通信线 1.3 数据传输 2. SPI总线时序及其4种工作模式 2.1 SPI数据移位示意 2.2 SPI四种工作模式 2.2.1 mode 0 &#xff1a;CPOL 0,CPHA0 2.2.2 mode 1&#xff1a; CPOL 0&#xff0c;CPHA 1 2.2.3 mode 2&#xff1a; C…

2024-07-14 Unity插件 Odin Inspector1 —— 插件介绍

文章目录 1 介绍2 模块3 学习目的 1 介绍 ​ Odin Inspector 是 Unity 的一个插件&#xff0c;拥有强大、自定义和用户友好的编辑器&#xff0c;而无需编写任何自定义编辑器代码&#xff0c;使得编程过程中的数据可视化更容易实现。 ​ 具体功能包括&#xff1a; 更舒适美观…

新一代大语言模型 GPT-5 对工作与生活的影响及应对策略

文章目录 &#x1f4d2;一、引言 &#x1f4d2;二、GPT-5 的发展背景 &#x1f680;&#xff08;一&#xff09;GPT-4 的表现与特点 &#x1f680;&#xff08;二&#xff09;GPT-5 的预期进步 &#x1f4d2;三、GPT-5 对工作的影响 &#x1f680;&#xff08;一&#xf…

FreeRTOS学习(1)STM32单片机移植FreeRTOS

一、FreeRTOS源码的下载 1、官网下载 FreeRTOS官方链接 官方下载速度慢&#xff0c;需要翻墙&#xff0c;一般选择第一个 2、直接通过仓库下载 仓库地址链接 同样很慢&#xff0c;甚至打不开网页&#xff0c;也不建议使用这种方法。 3、百度网盘 链接&#xff1a;https:…

ArrayList模拟实现

ArrayList模拟实现 ArrayList 的初步介绍常见操作 ArrayList 的简单模拟实现 ArrayList 的初步介绍 ArrayList也叫做顺序表&#xff0c;底层是一个数组。 在创建顺序表 时就应该规定 里面元素的数据类型&#xff0c;其中不能直接传基本数据类型&#xff0c;例如int、char。需要…

超简易高效的 AI绘图工具—与sd-webui一致界面,6G显存最高提升75%出图速率!(附安装包)

大家好&#xff0c;我是灵魂画师向阳 今天给大家分享一个基于Stable Diffusion WebUI 构建的AI绘图工具—sd-webui-forge&#xff0c;该工具的目标在于简化插件开发&#xff0c;优化资源管理&#xff0c;加速推理。 Forge承诺永远不会对Stable Diffusion WebUI用户界面添加不…

链接追踪系列-09.spring cloud项目整合elk显示业务日志

准备工作&#xff1a; 参看本系列之前篇&#xff1a;服务器安装elastic search 本机docker启动的kibana-tencent 使用本机安装的logstash。。。 本微服务实现的logstash配置如下&#xff1a; 使用腾讯云redis 启动本机mysql 启动本机docker 启动nacos,微服务依赖它作为…

rollup打包工具

rollup打包工具 在学习vite和vue3源码的时候&#xff0c;接触到了rollup&#xff0c;所以过来学习一下 什么是rollup rollup是一个模块化的打包工具&#xff0c;会将javascript文件进行合并。比起webpack&#xff0c;webpack在打包的时候会进行代码注入(保障兼容性)&#xf…

fortran简单排序算法,对一维、二维矩阵进行正序或倒序排序

fortran简单排序算法&#xff0c;对一维、二维矩阵进行正序或倒序排序 0. 引言1. 算法实现1.1 一维数组排序1.2 二维数组排序1.2 module文件 2. 结语 0. 引言 排序算法是计算机科学中的一项重要技术&#xff0c;它将一组数据按照特定的顺序排列起来。排序算法有很多种&#xff…

【云原生】Prometheus整合Alertmanager告警规则使用详解

目录 一、前言 二、Altermanager概述 2.1 什么是Altermanager 2.2 Altermanager使用场景 三、Altermanager架构与原理 3.1 Altermanager使用步骤 3.2 Altermanager工作机制 3.3 Altermanager在Prometheus中的位置 四、Altermanager部署与接入Prometheus 4.1 Altermana…

Codeforces Round 797 (Div. 3) F. Shifting String

感觉这种题写多了&#xff0c;第一眼就感觉是个图论&#xff0c;很经典的排列置换问题&#xff0c;首先连边&#xff0c;然后观察样例可以知道&#xff0c;大概是多个环的大小取lcm&#xff0c;但容易发现&#xff0c;环内部的循环节也对答案有影响&#xff0c;比如一个长度为4…

threadx 线程以及优先级调整案例

以正点原子stm32 f407板子为例子&#xff0c;如何创建工程 CubeMXCubeIDE在我之前的文章里提到了&#xff0c;这里我就不多重复。 有关线程优先级的两个参数 priority和preemption&#xff0c;我们来看看在官网是如何定义的 在main.c里面添加一个printf转串口的代码&#xff0…

Binder解析精炼

Binder原理解析精炼 1 注册服务 Server进程向binder驱动向Binder驱动发起服务注册请求 向Binder驱动申请创建一个XXXService的Binder的实体&#xff0c;Binder驱动为这个XXXService创建位于内核中的Binder实体节点以及Binder的引用 Binder驱动将注册请求转发给ServiceManager进…

Manim学习笔记05:实现向量的加法动画

以同一点 O&#x1d442; 为起点的两个已知向量 →a&#x1d44e;→&#xff0c; →b&#x1d44f;→&#xff0c;以 OA&#x1d442;&#x1d434;&#xff0c;OB&#x1d442;&#x1d435; 为邻边作 □OACB◻&#x1d442;&#x1d434;&#x1d436;&#x1d435;&#xff…

Yolov8 姿态估计

原文:Yolov8 姿态估计 - 知乎 (zhihu.com) YOLOv8论文还没有,官方默默又加了新模型:姿态估计。 现在你可以用YOLOv8做目标检测、实例分割、图像分类、目标跟踪、姿态估计,未完待续。。。。。。 一、Yolov8姿态估计 Yolov8的姿态估计模型是在COCO数据集训练的,目前支持…