C++入门基础(二)
6. 引用(引用就是取别名)
6.1 引用的概念和定义
引用不是新定义一个变量,而是给已存在变量取了⼀个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵,宋江叫"铁牛",江湖上人称"黑旋风";林冲,外号豹子头;
类型& 引用别名 = 引用对象;
C++中为了避免引入太多的运算符,会复用C语言的⼀些符号,比如前面的<< 和 >>,这里引用也和取地址使用了同⼀个符号&,大家注意使用方法角度区分就可以。
int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;

这串代码在底层的角度是这样的

对指针变量取别名:
int* p1 = &a;
int*& p2 = p1;
指针变量的使用: 
typedef struct ListNode
{
int val;
struct ListNode* next;
}LTNode, *PNode;
int main()
{
PNode plist = NULL;
ListPushBack(plist, 1);
return 0;
}
这里的*PNode是指把typedef struct ListNode* 定义为PNode。
6.2 引用的特性

这里的d的地址没变,说明d还是a的别名,d没有指向e,只是把e的值赋给了d。
当我们实现链表的时候,我们要删除一个结点,但这时的地址之间是相互关联的,因为引用不能改变指向,所以就不可能完成。所以C++的指针引用不能完全替代指针。

6.3 引用的使用
减少拷贝的案例:


传值传参会生成一个拷贝,传值返回也会生成一个拷贝。C++中是这样规定的,在红线这里进行一个传值返回,返回这个对象的时候, 他不会引用这个对象做函数调用的返回值,不会返回要返回的东西,它会生成一个临时对象,把这的值给临时变量,再用临时变量做这个整个表达式的返回值。STTop(st1)+=1;这是的加1就是加到临时对象上面。临时对象具有常性。
那临时对象是什么呢?
临时变量通常是指编译器在栈里面临时开一块空间存储中间值的这种,也有可能是用寄存器去存。
这里如何使用STTop(st1)+=1呢?只需要采用引用返回就可以了。传引用返回就是返回他的别名,也就是这里的2。也就a数组指向的top-1这里的对象。这时候就把引用对象给改变了。


typedef int STDataType;
typedef struct Stack
{
STDataType* a;
int top;
int capacity;
}ST;void STInit(ST& rs, int n = 4)
{
rs.a = (STDataType*)malloc(n * sizeof(STDataType));
rs.top = 0;
rs.capacity = n;
}// 栈顶
void STPush(ST& rs, STDataType x)
{
// 满了, 扩容
if (rs.top == rs.capacity)
{
printf("扩容\n");
int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
STDataType* tmp = (STDataType*)realloc(rs.a, newcapacity *
sizeof(STDataType));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
rs.a = tmp;
rs.capacity = newcapacity;
}
rs.a[rs.top] = x;
rs.top++;
}
int& STTop(ST& rs)
{
assert(rs.top > 0);return rs.a[rs.top - 1];
}
int main()
{
ST st1;
STInit(st1);
STPush(st1, 1);
STPush(st1, 2);
cout << STTop(st1) << endl;
//修改栈顶的数据呢
(STTop(st1)) += 1;
cout << STTop(st1) << endl;
return 0;
}
其实指针也可以做到:

并不是任何场景都能用引用返回(后面结合类和对象讲),比如说:

ret是局部变量,这里类似于野引用。
int* fun( )
{
int ret = 10;
return *ret;
}
这里的指针就越界了,指针越界不一定报错。


在vs中设置了抽查位置,这两个位置不分配给别人,给两个固定的值,在程序运行结束时看这两个位置的值有没有发生改变,没有被修改就说明没有越界。
6.4 const引用



这里是把x的这块空间拷贝给给y,x不能修改这块空间。
下面这个也是经典的权限放大:

下图这个是权限的缩小:


p1对于a的权限是只读不能写的,p1拷贝给给p2,p2又变成可读可写的了,p2的权限被放大,p5指向b的权限是可读可写的,p6指向p5也是可读可写的(这里不存在权限放大,因为const修饰的是p5本身不是指向的内容)。

a * 3这里存在一个临时变量,临时变量具有常性,这里加个const就行了。

这里的d给给rd其实也不是直接给过去的,中间也会产生一个临时变量来存储中间的结果。d给给中间的临时对象,这个临时对象是int类型,临时对象再给给rd。

类型转换会产生临时对象,d给了临时对象,这里的临时对象给给rd。也就是说rd引用了临时对象。
那上面这些到底有什么用呢?
这里的传值传参就不说了,对于引用传参
void fun(int& rx)如果变量 rx 不改变形参,建议前面加 const,void fun(const int& rx),加const的好处是什么呢?传参就非常宽泛。

const引用的价值是什么?
1.可以引用const对象
2.可以引用普通对象
3.可以引用临时对象
6.5 指针和引用的关系
野引用的案例:

从底层汇编的角度看,引用也是用指针实现的。
7. inline


可执行程序是一个文件,它会以一个进程的角度来进行运行(可执行程序会生成一个进程),进程才会给它分配内存,进程会把可执行程序的那个指令加载到内存的里面。
10000*100是指10000行指令*100行Add的指令总和的指令,10000+100是指10000行指令+100行Add的指令总和的指令。内联展开会导致一个问题:代码膨胀,代码膨胀会导致可执行程序变大,可执行程序变大,加载到进程也会变大,加载到内存导致内存变大。(可执行程序就是安装包)

// F.h# include <iostream>using namespace std;inline void f ( int i);// F.cpp# include "F.h"void f ( int i){cout << i << endl;}// text.cpp# include "F.h"int main (){
// 链接错误:⽆法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z)f ( 10 );return 0 ;}//那要怎么做呢?把// F.cpp这个文件中的f(int i)给注释掉# include "F.h"//void f ( int i)//{//cout << i << endl;//}在// F.h中定义inline void f ( int i){cout << i << endl;}
// 实现⼀个Add宏函数的常见问题
//#define Add(int a, int b) return a + b;//#define Add(a, b) a + b;//#define Add(a, b) (a + b)// 正确的宏实现(宏本质是一种替换)//宏函数坑很多,但是由于替换机制,调用函数时不用建立函数栈帧,能做到提效的作用。# define Add(a, b) ((a) + (b))// 为什么不能加分号 ?int main(){int ret = Add(1,2);//这里是将a替换成1,b替换成2;//int ret = Add(1,2);;//在这种场景下不会有问题cout << Add(1,2) << endl;//如果加分号在这种情况下就会报错,还有下面这种if(Add(1,2)){//...}cout << ret << endl;}// 为什么要加外⾯的括号 ?//有下面这种情况int main(){int ret = Add(1,2);//这里是将a替换成1,b替换成2;//int ret = Add(1,2);;cout << Add(1,2)*3 << endl;//cout << (1) + (2) * 3 << endl;}// 为什么要加里面的括号 ?int main(){int x =1,y = 2;Add(x & y ,x | y); // -> (x & y + x | y)}
8. nullptr
#ifndef NULL
#ifdef __cplusplus
#define NULL 0//C++
#else
#define NULL ((void *)0)//C语言
#endif
#endif
• C++11中引入nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换 成任意其他类型的指针类型。使用nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被 隐式地转换为指针类型,而不能被转换为整数类型。
相关文章:
C++入门基础(二)
6. 引用(引用就是取别名) 6.1 引用的概念和定义 引用不是新定义一个变量,而是给已存在变量取了⼀个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。比如:水浒传中李逵&…...
fabricjs 实现图像的二值化功能
一、效果图 二、图像二值化的作用 二值化是图像处理中常用的一种方法,其作用是将灰度图像转换为二值图像,即将图像中的像素点根据其灰度值分成两类:黑色和白色。这种处理方法可以帮助我们更清晰地识别图像中的目标,简化图像的复杂…...
修改本地hosts文件及外部访问机器本地hosts文件后,rancher UI网站仍然不能访问
原因排查 kubectl get svc # 输出: NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d17hkubectl get svc -A # 输出: NAMESPACE …...
西北潮榆林范儿,新榆林首个360°沉浸式剧场发布会闪耀亮相
这是一场城市更迭的未来大赏,也是一场商业蝶变的复合对话 8月3日,朗阁集团商业品牌发布会在榆林银杏熙悦酒店隆重启幕。朗阁集团董事长杨志成携众多集团领导出席;多家主流媒体代表联袂参加;喜茶、中影时光国际影城、汉堡王、鲍师傅…...
如何创建响应式移动端网页设计?最佳实践详解
移动端网页设计是一个耗时而复杂的过程开发,包括UI设计、UX设计、检测、发布、改进、维护和持续的错误修复。通过学习这篇文章,你将掌握什么是移动端网页,如何制作移动端网页,以及设计网页的技巧。 什么是移动端网页?…...
Python 如何进行Web抓取(BeautifulSoup, Scrapy)
Web抓取(Web Scraping)是一种从网站提取数据的技术。Python有许多用于Web抓取的库,其中最常用的是BeautifulSoup和Scrapy。 BeautifulSoup BeautifulSoup是一个用于解析HTML和XML文档的Python库,适合处理简单的Web抓取任务。它将…...
白骑士的PyCharm教学进阶篇 2.5 数据库连接与管理
系列目录 上一篇:白骑士的PyCharm教学进阶篇 2.4 Django开发支持 在Web开发中,数据库是必不可少的部分。PyCharm不仅是一款功能强大的IDE,还提供了丰富的数据库连接和管理工具,使开发者可以更方便地浏览和操作数据库。本篇将详细…...
(五)activiti-modeler 编辑器初步优化
最终效果: 1..首先去掉顶部的logo,没什么用,还占用空间。 修改modeler.html文件,添加样式: <style type"text/css"> #main-header{display: none; } #main{padding: 0px; } </style> 2.左边组…...
(学习总结12)C++类和对象3
C类和对象3 一、初始化列表二、类型转换三、static成员四、友元五、内部类六、匿名对象 以下代码环境在 VS2022。 一、初始化列表 之前我们实现构造函数时,初始化成员变量主要使用函数体内赋值,构造函数初始化还有⼀种方式,就是初始化列表&a…...
docxtpl,一个强大的 Python 库!
更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个强大的 Python 库 - docxtpl。 项目地址:https://docxtpl.readthedocs.io/en/latest/ 在日常工作中,自动生成和处理 Word 文档是一个常见需求。doc…...
捷途山海T2:超长续航,节能环保的驾驶新星
在当今的汽车市场中,消费者的购车选择日趋多样化,不再仅限于传统的燃油车。随着环保理念的深入人心以及人们对用车成本的日益关注,像捷途山海T2这样配备高效混动系统的车型逐渐受到大众的青睐。 捷途山海T2,以其杰出的节能性、强劲…...
[Day 45] 區塊鏈與人工智能的聯動應用:理論、技術與實踐
區塊鏈的可擴展性挑戰 概述 區塊鏈技術在過去幾年中取得了顯著的進展,其去中心化、透明和安全的特性使其在金融、供應鏈管理、醫療等領域得到了廣泛應用。然而,區塊鏈技術的一個重大挑戰是其可擴展性。可擴展性是指系統能夠有效處理日益增長的數據和用…...
白骑士的PyCharm教学实战项目篇 4.3 自动化测试与持续集成
系列目录 上一篇: 在现代软件开发过程中,自动化测试与持续集成(CI)是确保代码质量和快速交付的关键环节。PyCharm作为一款强大的集成开发环境(IDE),为自动化测试和持续集成提供了全面的支持。本…...
权限模块开发+权限与角色关联(完整CRUD)
文章目录 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)🌟 亮点功能📦 spring cloud模块概览常用工具 🔗 更多信息1.easycode生成代码1.配置2.AuthPermissionDao.java剪切到mapp…...
llama神经网络的结构,llama-3-8b.layers=32 llama-3-70b.layers=80; 2000汉字举例说明
目录 llama-3-8b.layers=32 llama-3-70b.layers=80 llama神经网络的结构 Llama神经网络结构示例 示例中的输入输出大小 实际举例说明2000个汉字文本数据集 初始化词嵌入矩阵 1. 输入层 2. 嵌入层 3. 卷积层 4. 全连接层 llama-3-8b.layers=32 llama-3-70b.laye…...
单细胞数据怎么表现genes mRNA表达的热图?
愿武艺晴小朋友一定得每天都开心 #热图 library("ComplexHeatmap") exp <- AverageExpression(subset(fasting_memory, Celltype %in% c("Pre-B")), layer = "data", #即CPM值 features …...
Java聚合快递对接云洋系统小程序源码
🚀【物流新纪元】聚合快递如何无缝对接云洋系统,效率飙升秘籍大公开!✨ 🔍 开篇揭秘:聚合快递的魅力所在 Hey小伙伴们,你是否还在为多家快递公司账号管理繁琐、订单处理效率低下而头疼?&#…...
MySQL——数据表的基本操作(三)修改数据表
有时候,希望对表中的某些信息进行修改,这时就需要修改数据表。所谓修改数据表指的是修改数据库中已经存在的数据表结构,比如,修改表名、修改字段名、修改字段的数据类型等。在 MySQL中,修改数据表的操作都是使用 ALTER…...
医学图像分割的基准:TransUnet(用于医学图像分割的Transformer编码器)器官分割
1、 TransUnet 介绍 TransUnet是一种用于医学图像分割的深度学习模型。它是基于Transformer模型的图像分割方法,由AI研究公司Hugging Face在2021年提出。 医学图像分割是一项重要的任务,旨在将医学图像中的不同结构和区域分离出来,以便医生可…...
java-swing编写学生成绩查询管理系统
本文是本人大二上实训项目-学生成绩查询管理系统,采用本项目使用Java、MySQL技术。界面框架由Java Swing搭建,用JDBC实现Java与MySQL的连接。 本项目适合初学java和mysql的同学,来做一些小项目来提升自己,因为兴趣所以想要做去尝…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
AtCoder 第409场初级竞赛 A~E题解
A Conflict 【题目链接】 原题链接:A - Conflict 【考点】 枚举 【题目大意】 找到是否有两人都想要的物品。 【解析】 遍历两端字符串,只有在同时为 o 时输出 Yes 并结束程序,否则输出 No。 【难度】 GESP三级 【代码参考】 #i…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...
如何理解 IP 数据报中的 TTL?
目录 前言理解 前言 面试灵魂一问:说说对 IP 数据报中 TTL 的理解?我们都知道,IP 数据报由首部和数据两部分组成,首部又分为两部分:固定部分和可变部分,共占 20 字节,而即将讨论的 TTL 就位于首…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
【Nginx】使用 Nginx+Lua 实现基于 IP 的访问频率限制
使用 NginxLua 实现基于 IP 的访问频率限制 在高并发场景下,限制某个 IP 的访问频率是非常重要的,可以有效防止恶意攻击或错误配置导致的服务宕机。以下是一个详细的实现方案,使用 Nginx 和 Lua 脚本结合 Redis 来实现基于 IP 的访问频率限制…...
【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)
LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 题目描述解题思路Java代码 题目描述 题目链接:LeetCode 3309. 连接二进制表示可形成的最大数值(中等) 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...
