目录

  • 引用
  • 内联函数
  • (C++11)
    • auto关键字
    • 基于范围的for循环
    • 指针空值---nullptr

引用

引用:指将变量以另一个名称来展现的。它并非是一个新变量而是一个别名,它们同指一块内存空间。就如古时那些有的人,亦或者是周树人,你说鲁迅是不是周树人呢?在这里插入图片描述

引用的形式:类型& 引用变量名(对象名) = 引用实体;
常引用: const 类型& 引用变量名(对象名) = 引用实体;
用常引用时要注意,他是常数的这个特性。

void TestRef()
{int a = 10;int& ra = a;//注意引用的类型要与引用的对象的类型一致!!!printf("%p\n", &a);printf("%p\n", &ra);
//常引用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;
}

引用的特点:
1.引用一定要初始化。
2.一个变量可以有多个引用。
3.一个引用不能指向多个变量。

引用的意义:
1.做参数。
2.做返回值。

对于引用做返回值有它的注意点:

#include<iostream>int& Add(int a, int b)
{int c=a+b;return c;
}
int main()
{int& ret = Add(1, 2);Add(3, 4);cout << "Add(1, 2) is :"<< ret <<endl;return 0;
}

你们认为结果是什么?其实是一个不可预测的值。
Add 函数里的 c 是局部变量,函数执行结束后,c 占用的内存会被释放。返回 c 的引用(int&)后,main 里的 ret 会变成悬空引用(指向已释放的内存 未定义行为)。后续调用 Add(3,4) 可能覆盖这片内存, 把 ret 原本指向的无效内存数据改掉 ,导致 ret 输出异常。
禁止返回局部变量的引用,否则会引发未定义行为;使用悬空引用 就是未定义行为 一切皆有可能。

做参数和返回值时 值与引用是有效率上的区别的:

#include<iostream>
#include <time.h>
using namespace std;
struct A { int a[10000]; };
void TestFunc1(A a) {
}
void TestFunc2(A& a)
{}
// 值返回
A TestFunc3(A a) { return a; }
// 引用返回
A& TestFunc4(A& a) { return a; }
int main()
{A a;// 以值作为函数参数size_t begin1 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc1(a);size_t end1 = clock();// 以引用作为函数参数size_t begin2 = clock();for (size_t i = 0; i < 10000; ++i)TestFunc2(a);size_t end2 = clock();// 分别计算两个函数运行结束后的时间cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;A b;A& B =b;// 以值作为函数的返回值类型size_t begin3 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc3(b);size_t end3 = clock();// 以引用作为函数的返回值类型size_t begin4 = clock();for (size_t i = 0; i < 100000; ++i)TestFunc4(B);size_t end4 = clock();// 计算两个函数运算完成之后的时间cout << "TestFunc3 time:" << end3 - begin3 << endl;cout << "TestFunc4 time:" << end4 - begin4 << endl;return 0;
}

在这里插入图片描述

通过上述代码的比较,发现传值和指针在作为传参以及返回值类型上效率相差很大。
传值:简单直接,但拷贝大型对象时效率低。
传引用:避免拷贝,效率更高,适合传递大对象或需修改实参的场景。
实际开发中,优先用传引用(或 const 引用) 处理复杂类型,减少不必要的性能损耗。

你们可能听说引用其实就是指针,这是有一定来由的。

在语法概念上引用就是一个别名,没有独立空间,和其引用实体共用同一块空间。
在底层实现上实际是有空间的,因为引用是按照指针方式来实现的。

引用和指针的不同点:

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

内联函数

内联函数:以inline修饰的函数叫做内联函数(在函数的返回值类型前面加inline)编译时C++编译器会在调用内联函数的地方展开(用函数体替换函数的调用),没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。

查看普通函数与内联函数的区别方法:

  1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add。
  2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不
    会对代码进行优化,以下给出vs2013的设置方式)
    debug模式下设置:
    开始:
    在这里插入图片描述
    改变后:
    在这里插入图片描述
    开始:
    在这里插入图片描述

改变后:
在这里插入图片描述
汇编代码:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
内联函数:
特性本质:以空间换时间,编译阶段用函数体替换调用,减少调用开销、提升效率,但可能使目标文件变大。

编译器处理:inline 是给编译器的建议,编译器可选择忽略,通常规模小、非递归、频繁调用的函数建议用,递归等情况编译器可能忽略该特性 。

适用与限制:用于优化规模小、流程直接、频繁调用函数,多数编译器不支持内联递归函数,75 行这类较长函数也难在调用点内联展开 。

inline 函数应该声明和定义不分开。因为inline被展开,就没有函数地址了,链接就会找不到。

inline函数其实还可以替代宏,那么我开始回忆宏的优缺点。
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
而我们可以在C++用这两种方法来代替宏。

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

(C++11)

auto关键字

在我们做的程序变得越来越大,我们所用的类型名称也会变得越来越难写(复杂)和含义不明确导致容易出错。对此我们之前可以用typedef来缩短名称,然而typedef 让类型别名和 const 的组合语义变得不直观,容易坑人。

typedef char* pstring;
int main()
{const pstring p1;    // 编译成功还是失败?const pstring* p2;   // 编译成功还是失败?return 0;
}

在早期C/C++中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量,但遗憾的
是一直没有人去使用它,因为局部变量默认就是自动存储类型,使用 auto 修饰属于多余操作, 其修饰效果和不修饰一样,因此无人使用。

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

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

auto 使用的细则:
1.auto 与指针和引用的注意事项:auto对于指针可以用auto或auto*,auto对于引用必须要加&:auto&。
2.auto对于同一行有多个变量的定义,他会先通过识别第一个变量类型,再用第一个变量类型赋给接下来的变量。因此要多个变量的类型一致。
3.auto不能用的场景:做函数参数,不能用在数组。
4. 为了避免与C++98中的auto发生混淆,C++11只保留了auto作为类型指示符的用法
5. auto在实际中最常见的优势用法就是跟C++11提供的新式for循环,还有lambda表达式等进行配合使用。

基于范围的for循环

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

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

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

基于范围的for循环使用条件:
1.因为是基于范围的,所以对于遍历的对象都要知其范围。
2.迭代的对象要实现++和==的操作

指针空值—nullptr

在C++98中的指针空值:NULL,NULL实际是一个宏,NULL可能被定义为字面常量0,或者被定义为无类型指针(void*)的常量。
那么就会出现问题:

void f(int)
{cout<<"f(int)"<<endl;
}
void f(int*)
{cout<<"f(int*)"<<endl;
}
int main()
{f(0);f(NULL);f((int*)NULL);return 0;
}

这里是想通过f(NULL)调用指针版本的f(int*)函数,但是由于NULL被定义成0,因此与程序的
初衷相悖。
在C++98中,字面常量0既可以是一个整形数字,也可以是无类型的指针(void*)常量,但是编译器
默认情况下将其看成是一个整形常量,如果要将其按照指针方式来使用,必须对其进行强转(void
*)0。

对于nullptr有下面的注意:

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

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

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

相关文章

wordpress网站的“管理员邮箱地址”有什么用?

在WordPress网站的“设置”-“常规”中设置的“管理员邮箱地址”有多种用途&#xff0c;以下是详细介绍&#xff1a; 一、用户注册相关 密码找回功能 当网站用户忘记密码时&#xff0c;他们会通过点击登录页面上的“忘记密码”链接来重置密码。WordPress系统会向管理员邮箱地…

202506 电子学会青少年等级考试机器人六级实际操作真题

更多内容和历年真题请查看网站&#xff1a;【试卷中心 -----> 电子学会 ----> 机器人技术 ----> 六级】 网站链接 青少年软件编程历年真题模拟题实时更新 202506 青少年等级考试机器人实操真题六级 一、实际操作 1. 主题&#xff1a;姿态传感器交互步进电机左右…

Centos 安装 redis

1.下载redis&#xff0c;这个自己去网上找吧。2.上传文件&#xff0c;redis-7.4.1.tar.gz3.解压&#xff1a;执行 tar -xf redis-7.4.1.tar.gz在进行安装之前&#xff0c;检查一下有没有make、gcc、python3、没有的话全部 yum install。安装完之后&#xff0c;如果报一下错误&a…

算法训练营DAY55 第十一章:图论part05

并查集理论基础 背景 当我们需要判断两个元素是否在同一个集合里的时候&#xff0c;我们就要想到用并查集。 并查集主要有两个功能&#xff1a; 将两个元素添加到一个集合中。判断两个元素在不在同一个集合 原理讲解 从代码层面&#xff0c;我们如何将两个元素添加到同一个…

docker相关操作记录

1.docker清理服务器上面没有用到的镜像#删除本地镜像 docker rmi $(docker images -q) #强制删除本地镜像 docker rmi $(docker images -q) -f2.docker查看日志docker logs c36c56e4cfa3 (容器id)3.所有运行或没有运行的镜像 docker ps -a4、停止container&#xff0c;这样才…

LInux基础学习笔记七

/dev/zero和/dev/null 是什么/dev/zero&#xff1a;一个零设备文件&#xff0c;读取时会不断返回\0字节&#xff08;零值字节&#xff09;&#xff0c;常用于创建空文件或格式化/dev/null&#xff1a;一个空设备文件&#xff0c;写入它的内容会被丢弃&#xff0c;相当于“黑洞”…

软件架构:系统结构的顶层设计与战略约束

软件架构&#xff1a;系统结构的顶层设计与战略约束软件架构是软件系统的“骨架”与“宪法”&#xff0c;它定义了系统的根本性组织结构&#xff0c;包括构成系统的关键构件、它们之间的组织关系、交互机制、约束原则以及指导性决策。它决定了系统在性能、可扩展性、可靠性、可…

基于spring boot的个人博客系统

2 开发技术 3 2.1 VUE框架 3 2.2 Mysql数据库 3 2.3 Spring Boot框架 3 2.4 layui介绍 4 本程序在设计结构选择上首选B/S&#xff0c;也是为了满足程序今后升级便利&#xff0c;以及程序低维护成本的要求。本程序的网络拓扑设计也会在下图展示&#xff0c;通过图形的方式来描述…

Excel制作尖刀图,直观展示业绩涨跌

Excel制作尖刀图&#xff0c;直观展示业绩涨跌效果展示下图是一个常见的两年业绩同比表&#xff0c;也是尖刀图很常见的数据源类型&#xff0c;但是这个数据格式是无法直接制作的&#xff0c;需要对数据进行加工。1.对数据进行逆透视使用excel进行逆透视&#xff0c;最常见的方…

两种路由模式(React-Router 8)

俩种路由模式 各个主流框架的路由常用的路由模式有俩种&#xff0c;history模式和hash模式,ReactRouter分别由createBrowerRouter和createHashRouter函数负责创建附带代码:import Login from "../page/Login"; import Article from "../page/Article"; imp…

【01】OpenCV C++实战篇——基于多项式插值的亚像素边缘定位算法

文章目录一. 背景二. 你的经历三. 代码实现(龟速版——单线程)3.1 梯度幅值3.1.1 生成 8 个方向模板3.1.2 计算梯度3.1.3 显示梯度图像3.1.4 程序运行演示3.2 梯度方向 &#xff08;梯度最大幅度值和方向&#xff09;3.3 单像素边缘3.4 梯度单像素边缘提取 运行测试四 、亚像素…

400V降24V,200mA,应用领域:从生活到工业的 “全能电源管家”WD5208

WD5208 电源芯片&#xff1a;小身材蕴藏大能量的电源控制新星在电源芯片的技术星河中&#xff0c;WD5208 凭借独特性能与广泛适用性崭露头角&#xff0c;成为众多电子设备电源方案的优选。本文将全面解析这款芯片的核心优势、应用场景与技术细节&#xff0c;展现其 “小身材&am…

C++ 引用 和 指针 的区别

特性引用指针初始化不能为 null&#xff0c;必须绑定到有效的对象可以为 null&#xff0c;不指向任何对象重新绑定不能重新绑定&#xff0c;一旦初始化后始终引用同一个对象可以重新指向其他对象内存占用不占用额外内存&#xff0c;编译器通常将其优化为所引用的对象占用额外内…

Claude Code实战体验:AI智能编程助手如何重塑开发工作流?

一、背景介绍 AI大模型的爆发&#xff0c;让各种智能编码工具如雨后春笋般涌现。Claude Code就是其中非常有代表性的一款——它不仅能补全代码、查找Bug&#xff0c;还能理解复杂需求&#xff0c;甚至帮你写文档、生成测试用例。作为一名全栈开发者&#xff0c;我和团队最近几个…

centos7 个人网站搭建之gitlab私有化部署实现线上发布

文章目录 效果展示架构设计申请免费阿里云服务器尝试连接远程服务 开放端口申请域名 绑定云服务器组网网关服务器配置转发代理网关服务器配置ssl 证书问题排查证书申请时报错&#xff1a;Set the \server_name\ directive ti use the Nginx installer. gitlab私有化部署搭建git…

小米4A千兆版路由器刷机,解决Telnet无法连接问题

刷机极容易变砖&#xff0c;建议完全理清步骤后再进行操作 工具准备 1、小米4A千兆版路由器&#xff08;注意一定是千兆版&#xff0c;只是4A无千兆按下列步骤会变砖&#xff09;&#xff0c;适配电源线 2、网线一根 3、需保证刷机过程中网线接入是有网的&#xff0c;无需账号认…

计算机网络:如何将一个B类IP地址分为4个子网

要将一个B类IP地址划分为4个子网&#xff0c;需通过子网掩码扩展&#xff08;即借位&#xff09;来实现。以下是详细步骤和原理&#xff1a; 一、B类IP地址的基础特性 默认网络位&#xff1a;B类地址前16位为网络位&#xff08;标识网络&#xff09;&#xff0c;后16位为主机位…

K8S 性能瓶颈排查

K8S 性能瓶颈排查 随着业务量增长,Kubernetes 集群经常出现: • Pod 启动慢? • API 响应慢? • 节点 CPU 飙高? • 服务无故中断? 这可能是性能瓶颈在悄悄作祟。 性能瓶颈全局视角 # K8S 性能瓶颈排查思维导图- 集群层面- API Server 响应慢- Etcd 压力大- 控制面组件…

实习005 (web后端springboot)

五种创建方式一、方法一&#xff08;直接创建&#xff09;二、方法二&#xff08;阿里云&#xff09;三、方法三&#xff08;从官网&#xff09;或者说四、方法四、&#xff08;案例云官网&#xff09;五、方法五、&#xff08;自己写&#xff09;先构建javaweb项目刷新后还是出…

基于vscode连接服务器实现远程开发

目录 一、背景介绍 1.1 什么是远程开发 1.2 版本清单 二、以Java项目开发为例 2.1 安装远程开发插件 2.2 安装语言开发插件 2.3 新建ssh连接 2.4 打开服务器目录 一、背景介绍 1.1 什么是远程开发 远程开发是基于服务器环境进行实现本地开发操作&#xff0c;…