C++相关基础概念之入门讲解(下)

1. 引用

​
int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}
引用 不是新定义一个变量,而 给已存在变量取了一个别名 ,编译器不会为引用变量开辟内存空
间,它和它引用的变量 共用同一块内存空间(初期这么理解就好,实际上在底层是开了空间的)
引用的使用方法就是:类型 & 引用变量名 ( 对象名 ) = 引用实体;
举个例子:

在这个代码里面aa是a的别名,aa++了,也就是a++;所以这里的输出是11;

举个例子,现在有一个人叫小明,我们给他取一个别名叫明明,明明去吃饭了,那是不是小明也去吃饭了,引用就是这个意思。

注意: 引用类型 必须和引用 实体 同种类型 。也就是说在上面这个代码里面,aa要和a是同一个类型(int)。

1.1 常引用

​int main()
{const int a=10;int& aa=a;aa++;cout<<aa<<endl;
}

在这个代码里面,如果a是const int类型的,那就不可以对aa进行++的操作(会报错)。

举个例子,小明不可以吃饭,那也就是说明明不可以吃饭。

1.2 传值返回与传引用返回

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直
接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效
率是非常低下的,尤其是当参数或者返回值类型非常大时(比如说map<string,string>),效率就更低。
传值返回:
int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

在这段代码里面,最终的结果是2。但是他在return a的时候产生了一份临时拷贝,然后把这个临时拷贝赋值给了b。我们前面说的消耗就是在这里。

PS:之所以要拷贝的原因涉及到函数栈帧的创建与销毁,简单来说就是a出了这个Fanc就会自动销毁,所以编译器要通过产生临时拷贝的方式来进行赋值。

传引用返回:

​int& Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

在这段代码里面,a其实是有危险的,因为是&,所以在这里并没用产生a的临时拷贝,也就是说在这里实际上造成了野指针现象。

修改的办法有两种。

一种是加一个全局变量

int c;//  全局变量int& Fanc(int a) {c = a + 1;  return c;   
}int main() {int b = 1;b = Fanc(b);cout << b << endl; return 0;
}

传入的是全局变量(或者静态变量也可以),所以在这里并不会被销毁。

还有一种是通过引用传递参数

int& Fanc(int& a) {a++;        // 直接修改传入的参数return a;   // 返回传入参数的引用
}int main() {int b = 1;Fanc(b); cout << b << endl;  return 0;
}
通过引用传递参数,直接修改传入的参数并返回其引用

1.3 传值、传引用

首先,传值和传引用与传值返回与传引用返回不是同一个东西。

传值:

​​int Fanc(int a)
{a++;return a;
}int main()
{int b=1;b=Fanc(b);cout<<b<<endl;return 0;
}

这个就是我们在一开始的学习中使用函数的方式。消耗也比较大。

传引用:

​
​int Fanc(int& a)
{a++;return a;
}int main()
{int b=1;Fanc(b);//没有了b=...cout<<b<<endl;return 0;
}​

直接修改传入的参数,而不需要返回值。同时代价也小。

1.4 引用和指针的区别

在C++中,引用和指针都是用来间接访问变量的机制,但它们之间有一些重要的区别:

1. 引用是变量的别名,而指针是一个独立的实体。引用在声明时必须初始化,并且一旦引用和原变量绑定后,就无法再绑定到其他变量(这一点很重要);而指针可以在声明后指向不同的变量。

2. 引用不需要使用解引用操作符(*)来访问其绑定的变量,而指针需要使用解引用操作符(*)来访问其指向的变量。

3. 引用不能指向空值(null),而指针可以指向空值。

4. 指针可以进行算术运算,而引用不支持。

总的来说,引用更直观和安全,因为它不需要对空值进行处理,而指针更灵活,因为它可以指向不同的对象和进行算术运算。在实际使用中,应根据具体情况选择合适的机制。

2. 内联函数

inline 修饰 的函数叫做内联函数, 编译时 C++ 编译器会在 调用内联函数的地方展开 ,没有函数调
用建立栈帧的开销,内联函数提升程序运行的效率。
inline int add(int a, int b)
{return a + b;
}int main() 
{int result = add(3, 4);  // 编译器可能会将 add 函数直接插入此处cout << "Result: " << result << endl;return 0;
}

内联函数的本质就是替换,通过把main函数里面的add直接转换成a+b,通过这样的方式来提升效率。

2.1 内联函数特性

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

3. auto关键字

auto我从刚刚学到他的时候认为没什么用,但是当我学到后面的时候,我才发现他是那么的好用,因为到后面很多时候类型是一层套一层,就是说会特别的长,这个时候auto的作用就体现出来了。

他的本质就是让编译器自动推导类型。换种说法就是把我们的这部分工作交给了编译器。

3.1 auto使用时候的注意事项

使用 auto 定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导 auto
的实际类型 。因此 auto 并非是一种 类型 的声明,而是一个类型声明时的 占位符 ,编译器在编
译期会将 auto 替换为变量实际的类型
int main()
{auto x = 10,y=3;return 0
}

上面这种就是合法的,因为auto在同一行只会进行一次推导,如果说y=3.3,那么编译器就会报错。

3.2 auto不能推导的类型

auto不可以作为函数的参数类型,比如说:

auto fanc(auto a)
{.......
}

这种是不合法的(其实没有什么别的原因,就是设计者在设计的时候没有允许这种用法,我们在后面会学到一种template<class T>的东西,他可以实现我们上面想要达到的目的)。

同时,auto也不可以作为数组的类型,简单来说就是:

int main()
{auto arr[]={1,2,3,4,5,6}return 0;
}

这种也是不可以的(原因如上)。

4. 范围for

对于一个 有范围的集合 而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误(如越界访问)。因 此C++11 中引入了基于范围的 for 循环。 for 循环后的括号由冒号 分为两部分:第一部分是范 围内用于迭代的变量,第二部分则表示被迭代的范围
void TestFor()
{int arr[] = { 1, 2, 3, 4, 5 };for(auto& a : arr)a *= 2;
}

这就是范围for的用法,通过这样的方式就可以使arr里面的数都*上2。

PS:加上引用就可以改变arr,如果说是想要改变范围for里面的数组,那最好就是在auto后面加一个&。

4.1 范围for的原理

范围for的底层就是迭代器(iterator),他在编译器编译的时候就会修改为迭代器。

所以说我们在里面想要遍历或者修改的东西必须有beginend的方法,beginend就是for循环迭代的范围。

5. 空指针nullptr

程序本意是想通过 f(NULL) 调用指针版本的 f(int*) 函数,但是由于 NULL 被定义成 0 ,因此与程序的
初衷相悖。 因此发明了nullptr,
PS: 在使用 nullptr 表示指针空值时,不需要包含头文件。
因此我们在使用的时间候直接把他当做一个不能表示0的NULL去使用就好。

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

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

相关文章

注意力机制,本质上是在做什么?

本文以自注意机制为例&#xff0c;输入一个4*4的矩阵 如下&#xff1a; input_datatorch.tensor([[1,2,3,4], [5,6,7,8], [9,10,11,12], [13,14,15,16] ],dtypetorch.float) 得到Q和K的转置如下。 此时&#xff0c;计算QK^T ,得到如下结果 第一行第一个位置就是第一条样本和第…

记一次wsl2+docker无法运行的经历

前情提要 由于某个大创项目的需要和对猫娘机器人的迫切渴求&#xff08;bushi 需要在电脑里面安装docker desktop。由于电脑里面安装了wsl2环境 因此决定使用wsl2dockerdesktop的方式配置docker 遇到的问题 在像往常一样安装docker desktop并且启动时 提示错误&#xff1a; …

PageHelper插件依赖引入不报错,但用不了

情况: 父模块pom. Xml 引入1. 4. 0以上版本的pagehelper-spring-boot-starter。 要用到插件的子模块&#xff0c;去掉版本号&#xff0c;引入和父模块一样的依赖。 引入成功&#xff0c;没有报错&#xff0c;但是打开右边的maven里面没有找到PageHelper插件。 终端清空并重…

Windows搭建免翻墙的BatteryHistorian

文章参考 GitCode - 全球开发者的开源社区,开源代码托管平台 免翻墙的BatteryHistorian主要原理&#xff1a;修改go源码 1.安装Java环境 1.点击下载 Java JDK&#xff0c;并安装,一路next 2.java -version 检验是否安装成功 2.安装Git工具 1、点击下载 Git&#xff0c;并…

项目中pnpm版本和全局pnpm版本不一致

项目中pnpm版本和全局pnpm版本不一致 检查package.json中&#xff0c;是否存在"packageManager": “pnpm8.6.10”&#xff0c;限制了pnpm的版本。

透析Vue的nextTick原理

nextTick 是 Vue.js 中的一个核心机制&#xff0c;用于在 下一次 DOM 更新周期后 执行回调函数。它的核心原理是 利用 JavaScript 的事件循环机制&#xff08;Event Loop&#xff09;&#xff0c;结合微任务&#xff08;Microtask&#xff09;或宏任务&#xff08;Macrotask&am…

WRF/Chem 模式技术解读:为大气污染治理提供有力支撑

技术点目录 第一部分、WRF-Chem模式应用案例和理论基础第二部分、Linux环境配置及WRF-CHEM第三部分、WRF-Chem模式编译&#xff0c;排放源制作第四部分、WRF-Chem数据准备&#xff08;气象、排放、初边界条件等&#xff09;&#xff0c;案例实践第五部分、模拟结果提取、数据可…

ccfcsp2701如此编码

//如此编码 #include<iostream> using namespace std; int main(){int n,m;cin>>n>>m;int a[21],b[21],c[21];for(int i1;i<n;i){cin>>a[i];}c[0]1;for(int i1;i<n;i){c[i]c[i-1]*a[i];}b[1](m%c[1])/c[0];int s1,s20;for(int i2;i<n;i){s2s2…

74HC04(反相器)和74HC14(反相器、施密特触发器)的区别

74HC04和74HC14的具体区别详解 同样具有反相器功能&#xff0c;你知道74HC04和74HC14的具体区别吗&#xff1f; 74HC04 对于74HC04很好理解&#xff0c;输入低电平&#xff0c;输出高电平&#xff1b;输入高电平&#xff0c;输出低电平。 建议操作条件&#xff1a; 下图是TI的…

如何缓解大语言模型推理中的“幻觉”(Hallucination)?

目录 如何缓解大语言模型推理中的“幻觉”&#xff08;Hallucination&#xff09;&#xff1f; 1. 什么是大语言模型的“幻觉”&#xff08;Hallucination&#xff09;&#xff1f; 幻觉的常见类型 2. 如何缓解大模型的幻觉问题&#xff1f; 方法 1&#xff1a;使用知识检索…

Linux权限管理详解

Linux权限管理系统 Linux作为一个多用户操作系统&#xff0c;其权限管理系统是保障系统安全的重要组成部分。通过合理设置文件和目录的权限&#xff0c;可以有效控制用户对系统资源的访问。 一、基本权限概念 Linux系统中的权限分为三类&#xff1a; 读权限(r)&#xff1a;…

第十四次CCF-CSP认证(含C++源码)

第十四次CCF-CSP认证 卖菜满分思路 买菜满分思路 再卖菜满分题解&#xff08;差分约束&#xff09;solution 1(枚举 correct but 超时)solution 2(正解) 卖菜 题目链接 满分思路 就是模拟一下这个调整第二天菜价的过程&#xff0c;其中对于两种只有一个邻居的情况下做出调整&…

CCBCISCN复盘

AWDP – ccfrum 自己搭了一下环境, 复现一下这道题目, 之前比赛的时候完全没想到这个漏洞要怎么打, 修也不知道要怎么修, 就仅仅是对用户名的账号和密码进行了一下过滤, 完全没起到作用, 唉, 实在太菜 如果想要尝试复现的话可以尝试拉取这个镜像, 我打完之后就直接把这个容器给…

(每日一道算法题)交易逆序对的总数

LCR 170. 交易逆序对的总数 - 力扣&#xff08;LeetCode&#xff09; 在股票交易中&#xff0c;如果前一天的股价高于后一天的股价&#xff0c;则可以认为存在一个「交易逆序对」。请设计一个程序&#xff0c;输入一段时间内的股票交易记录 record&#xff0c;返回其中存在的「…

【操作系统】共享数据的竞争问题

共享数据的竞争问题 问题&#xff1a;保护中断与主程序共享的avg_data方法一&#xff1a;使用关中断保护1. 添加关中断宏2. 修改数据读取代码3. 修改中断服务程序&#xff08;ISR&#xff09; 方法二&#xff1a;使用原子操作&#xff08;需平台支持&#xff09;1. 定义原子类型…

VS010生成可由MATLAB2016调用的DLL文件方法

亲测实用&#xff0c;不用配置杂七杂八的依赖项 1&#xff1a;新建Win32的DLL输出项目 2&#xff1a;修改为release模式 3&#xff1a;添加calc.cpp文件&#xff0c;即要导出的函数myadd&#xff1a; #include "calc.h" __declspec(dllexport) int myadd(int a,in…

机器学习Pandas_learn4

import pandas as pddef calculate_goods_covariance():# 定义商品销售数据字典goods_sales_data {"时期": ["一期", "二期", "三期", "四期"],"苹果": [15, 16, 3, 2],"橘子": [12, 14, 16, 18],&quo…

优选算法系列(3.二分查找 )

目录 一.二分查找&#xff08;easy&#xff09; 题目链接&#xff1a;704. 二分查找 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; 代码&#xff1a; 二.在排序数组中查找元素的第⼀个和最后⼀个位置&#xff08;medium&#xff09; 题目链接&#xff1a;34.…

DAY36贪心算法Ⅴ

56. 合并区间 - 力扣&#xff08;LeetCode&#xff09; class Solution { static bool cmp(vector<int>&a,vector<int>&b){return a[0] < b[0]; } public:vector<vector<int>> merge(vector<vector<int>>& intervals) {so…

阿里云服务器部署 五 Nginx + springboot

Nginx的部分配置 1. 基础容灾配置&#xff08;被动健康检查&#xff09; 在 upstream 块中&#xff0c;通过 max_fails 和 fail_timeout 参数定义故障转移规则&#xff1a; 在 upstream 块中&#xff0c;通过 max_fails 和 fail_timeout 参数定义故障转移规则&#xff1a;…