初始C++(二)

news2024/12/30 3:52:18

前言:

        C++相对于C语言还有很多区别,接下来我们继续介绍

函数重载:

        很好理解,就是Java中的函数重载。C++加了函数的修饰,通过函数修饰规则去找。C语言是直接通过函数名查找,C++是通过修饰后的函数名去查找。

引用:

        注意,这个知识点很重要。引用不是新定义一个变量,而是给已经存在的变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量公用同一块内存空间。

        相当于给其他人取了别名。

int main()
{
	int a = 0;
	//引用:b是a的别名
	int& b = a;

	//地址都是一样的
	cout << &a << endl;
	cout << &b << endl;
	return 0;
}

        可以发现, 地址都是一样的。

        我们可以不用传地址,通过引用(取别名)的方式交换实参的值。

void Swap(int& a, int& b)
{//a是x的别名 b是y的别名
	//所以可以完成交换
	int tmp = a;
	a = b;
	b = tmp;
}

int main()
{
	int x = 1, y = 0;
	Swap(x, y);
	cout << x << endl;
	cout << y << endl;

	return 0;
}

        这里可以看出,引用有点类似于指针;引用确实可以改变实参,其实引用本事就是为了方便我们的学习,但是我们如果想要学得更好,还是需要学好指针的。但是不能完全替代指针,比如一个链表,还是需要用到指针的。

typedef struct ListNode
{
	int val;
	struct ListNode* next;
}LTNode;


//void LishPush(LTNode** phead, int x)
//这两者是等价的,我们可以通过引用改变指针指向
void LishPush(LTNode*& phead, int x)
{

}

        之前我们使用链表,往里面插入数据需要传二级指针,现在有了引用就不需要传入二级指针,只需要传入指针的引用即可。

        引用在使用的时候必须先初始化;一个变量可以有多个引用。

        引用一旦引用一个实体,便不能引用其他实体。

int main()
{
	int x = 0, z = 0;
	int& y = x;
	//是y变成z的别名呢?
	//还是z赋值给y?
	//是z赋值给x
	y = z;
	return 0;
}

        注意这里y是x的别名,之后将z的值赋给x。

引用和指针的区别:

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

         语法上引用不开空间,我们通过反汇编来观察:

        可以发现底层都是指针,但是引用语法上不开空间。

        因为就是起了一个别名,所以本质大小还是类型本身的大小。 

注意事项:

        我们先来看一段代码:

int* p = NULL;
int& r = *p;
//这里我们不能只看语法层
//这里就要看底层,是一个指针存放了空指针

        一旦打印,就会崩溃,所以一定注意!

权限:

        我们必须将权限单独来讲,每个变量都会存在权限。

//权限的方法
//m只读
//n变成m的别名,n的权限是可读可写
//权限只能缩小,不能放大
const int m = 0;
int& n = m;

        因为取别名可以将权限放大。 权限只能缩小,不能放大。

int x = 0;
const int& y = x;
x++;//可以修改,只是不能够y去修改

        我们再来观察一个代码: 

int main()
{
	double d = 12.34;
	//类型转换会发生临时变量
	int i = d;

	int& y = d;//这句是错误的


	const int& r = d;


	return 0;
}

        因为临时变量具有常性,所以我们只能添加const语法才正确。 

 

内联函数:

        如果我们要频繁使用一个函数时,如果这个函数是一个小函数,但是需要频繁使用,C语言一般是使用宏,这样可以提高效率。

        但是宏是进行宏替换,很容易出现问题,一般是不建议使用宏去完成一个函数的,那么我们在C++该如何解决这个问题呢?

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

        在Debug版本下内联函数默认不展开,因为这样方便调试。

        此时可以看到call,就说明还是去建立了函数栈帧。此时我们就需要去更改一些配置才能看到具体内联函数是如何操作的。

        当内联函数比较大时,就不再会进行展开。

        inline是一种以空间换时间的做法,如果编译器将函数当成了内敛函数处理,在编译阶段,会用函数体替换函数调用。

        缺陷:可能会使目标文件变大 优势:少了调用开销,提高程序运行效率。

        inline对于编译器而言只是一个建议,不用编译器关于inline实现机制可能不同,一般建议:将函数规模较小(函数不长,取决于编译器内部实现)不是递归切频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。

        也就是说,内联函数是否展开取决于编译器。

        这里我们不考虑函数的栈帧,如果展开,编译出来的可执行程序会变大。

        内联不能声明和定义分离!

        因为在链接时会符号汇总,回去找函数的地址,但是内联函数是没有地址的(因为没有call),直接被展开,所以会报链接错误。所以使用内联函数时不要声明和定义分离。

auto:

        auto可以替代写起来比较长的类型定义,简化代码。

int main()
{
	int a = 10;
	int b = a;
	auto c = 'a';

	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;

	return 0;
}

        typeid可以帮助我们去看一个对象的类型。

int x = 10;
auto a = &x;
//指定必须是指针
auto* a1 = &x;

        我们可以用auto来接受指针,可以在后面加上*也可以不加上*,但是一旦加上*,就指定它一定是一个指针变量。 

        auto不能作为函数的形式参数。

        C++中有增强for循环,叫做范围for,我们可以利用auto来改善增强for循环。

int main()
{
	int arry[] = { 1,2,3,4,5 };
	for (auto x : arry) {
		cout << x << " ";
	}
	return 0;
}

        如果我们想利用增强for循环来改变数组内容,不能直接改变,因为临时变量是其拷贝,所以我们加上引用即可修改。 

int main()
{
	int arry[] = { 1,2,3,4,5 };
	for (auto& x : arry) {
		x += 1;
	}

	for (auto x : arry) {
		cout << x << " ";
	}
	return 0;
}

        在函数中,不能用增强for循环对数组进行遍历,因为传过去的时指针,其只能对数组使用。

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

int main()
{
	int arry[] = { 1,2,3,4,5 };
	TestFor(arry);

	//for (auto& x : arry) {
	//	x += 1;
	//}

	//for (auto x : arry) {
	//	cout << x << " ";
	//}
	return 0;
}

 

        因为C/C++追求效率,所以不支持传数组。

nullptr:

        我们先看一段代码:

void f(int i)
{
	cout << "f(int)" << endl;
}

void f(int* p)
{
	cout << "f(int*)" << endl;
}

int main()
{
	f(0);
	f(NULL);
	return 0;
}

        因为NULL宏定义为0,所以此时调用的是一个函数。这就是C语言的缺陷。

f((int*)NULL);

        此时只能这样修改。所以C++引入了nullptr关键字。

        使用nullptr表示指针空值时,不需要包含头文件,因为nullptr是C++11作为新关键字引入的。

        sizeof(nullptr)与sizeof((void*)0)所占字节数相同。为了提高代码健壮性,在后续表示指针空值是建议最好使用nullptr。

void f(int i)
{
	cout << "f(int)" << endl;
}

void f(int* p)
{
	cout << "f(int*)" << endl;
}

int main()
{
	f(0);
	f((int*)NULL);
	f(nullptr);
	return 0;
}

总结: 

        OK了老铁焖,我们已经基本上把所有C++基础语法学完了,当然你要有C语言基础,期待下一篇,就是类和对象!

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

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

相关文章

蓝桥青少一月 STEMA-Python 测评第一题

第一题&#xff08;难度系数 2&#xff0c;18 个计分点&#xff09; (注.input()输入函数的括号中不允许添加任何信息) 编程实现&#xff1a; 给定一个正整数 N&#xff0c;输出 N 除以 3 的商。 输入描述&#xff1a;输入一个正整数 N 输出描述&#xff1a;输出 N 除以 3 的商…

Faststone Capture:高效屏幕捕获神器评测【AI写作】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

Cesium 展示——让加载的实体置于顶层,不被其他加载的元素所遮挡,包括地形,一键置顶

文章目录 需求分析需求 本案例中展示了加载了3DTiles后又在其表面添加了一个实体,实体被遮挡,随着视角变换,实体被展示出来,如下图所示 分析 disableDepthTestDistance:指定从相机到禁用深度测试的距离,由于深度测试的存在,我们的对象很多时候会被地形挡住,我们设置dis…

AI电视起风,三星电视打破“隔代飞跃”,在AI纪元再次领跑

作者 | 曾响铃 文 | 响铃说 要说什么是当下最热的话题&#xff0c;刚落下帷幕的北京车展一定是其中之一&#xff0c;除了各类让人眼花缭乱的新车&#xff0c;纷至沓来的各界行业大佬&#xff0c;也让车展话题度被不断拉高。在此之外&#xff0c;此次车展还刮起了一股“旋风”…

Orange3数据可视化(小提琴图)

小提琴图 小提琴图和箱线图类似&#xff0c;用来显示数据分布和概率密度。结合了箱线图和密度图的特征&#xff0c;用来显示数据的分布形状。 输入 数据: 输入数据集 输出 选中的数据: 从图中选中的实例 数据: 增加了一列&#xff0c;显示数据点是否被选中 …

DUX 主题 版本:8.2 WordPress主题优化版

主题下载地址&#xff1a;DUX 主题优化版.zip 支持夜间模式、快讯、专题、百度收录、人机验证、多级分类筛选&#xff0c;适用于垂直站点、科技博客、个人站&#xff0c;扁平化设计、简洁白色、超多功能配置、会员中心、直达链接、自动缩略图

如何从未入库的gerrit中撤销一个文件

用一个例子说明 比如有一个提交里面的default.xml的修改没有必要&#xff0c;需要从未入库的gerrit中移除 步骤如下&#xff1a; 1.做reset操作 git reset HEAD^ packages/SettingsProvider/res/values/defaults.xml 2.做checkout操作 git checkout packages/SettingsProv…

【算法系列】栈

目录 leetcode题目 一、删除字符串中的所有相邻重复项 二、比较含退格的字符串 三、基本计算器 II 四、字符串解码 五、验证栈序列 六、有效的括号 七、最小栈 八、逆波兰表达式求值 九、用栈实现队列 十、用队列实现栈 leetcode题目 一、删除字符串中的所有相邻重…

Mybatis存储数据将数据转为json

第一种方法 先创建一个表类型如下 创建一个项目&#xff0c;写一个接口 &#xff0c; 写一个JsonTypeHandler类继承BaseTypeHandler public class JsonTypeHandler<T> extends BaseTypeHandler<T> {private Class<T> clazz;//构造函数 --- >接收一个 Cl…

在数据分析中所需要运用到的概率论知识

数据分析 前言一、总体二、样本三、统计抽样抽取的基本准则 四、随机抽样抽签法随机数法 五、分层抽样六、整群抽样七、系统抽样八、统计参数常用的分布函数参数 九、样本统计量十、样本均值和样本方差十一、描述样本集中位置的统计量样本均值样本中位数样本众数 十二、描述样本…

计算机发展史故事【5】

电脑创世纪 全世界在隆隆的炮火声中迎来了1943 年。硝烟密布&#xff0c;战鼓催春&#xff0c;战争的迫切需要&#xff0c;像一只有力的巨手&#xff0c;为电脑的诞生扫清障碍&#xff0c;铺平道路。 4 月9 日&#xff0c;美国马里兰州阿贝丁&#xff0c;陆军军械部召集的一次会…

深度学习论文代码研读系列(1)Transformer:Attention Is All You Need

目录 摘要 1 引言 2背景 3模型架构 3.1编码器和解码器堆栈编码器&#xff1a; 3.2 Attention 3.2.1 Scaled Dot-Product Attention 3.2.2多头注意力 3.2.3注意力在我们的模型中的应用 3.3位置前馈网络 3.4嵌入和Softmax 3.5位置编码 4为什么自注意力 5 Training 6…

小红书释放被封手机号 无限注册

前几年抖音也可以释放被封手机号 那时候都不重视 导致现在被封手机号想释放 基本不可能的 或者就是最少几百块 有专业的人帮你通过某些信息差释放 本教程是拆解 小红书被封手机号怎么释放&#xff0c;从今年开始&#xff0c;被封的手机号无法注销了 所以很困扰 那么本教程来…

AI绘画Stable Diffusion 插件篇:智能标签提示词插件sd-danbooru-tags-upsampler

大家好&#xff0c;我是向阳。 关于智能标签提示词插件&#xff0c;在很早之前就介绍过很多款了&#xff0c;今天再给大家介绍一款智能标签提示词插件sd-danbooru-tags-upsampler。该智能提示词插件是今年2月23号才发布的第一版V0.1.0&#xff0c;算是比较新的智能提示词插件。…

Semi-decentralized Federated Ego Graph Learning for Recommendation

论文概况 本文是2023年WWW的一篇联邦推荐论文&#xff0c;提出了一个半去中心化的联合自我图学习框架。 Introduction 作者提出问题 现有的推荐方法收集所有用户的自我图来组成一个全局图&#xff0c;导致隐私风险。联合推荐系统已被提出来缓解隐私问题&#xff0c;但在客户…

【半夜学习MySQL】数据库概念详解探索数据库到底是如何存储的?

&#x1f3e0;关于专栏&#xff1a;半夜学习MySQL专栏用于记录MySQL数据相关内容。 &#x1f3af;每天努力一点点&#xff0c;技术变化看得见 文章目录 什么是数据库主流数据库与数据库分类数据库的基本使用数据库的启动及关闭查看配置文件与数据库存储位置连接数据库服务器服务…

Linux进程——Linux环境变量

前言&#xff1a;在结束完上一篇的命令行参数时&#xff0c;我们简单的了解了一下Linux中的环境变量PATH&#xff0c;而环境变量不只有PATH&#xff0c;关于更多环境变量的知识我们将在本篇展开&#xff01; 本篇主要内容&#xff1a; 常见的环境变量 获取环境变量的三种方式 本…

[性能优化] ScrollView视图优化为循环列表

问题描述&#xff1a; 原先商城的物品栏中的item 是load在一个scrollView 下&#xff0c;用于滑动查看。仅仅在父级panel下是使用了NGUI原生的scrollview 组件&#xff0c;随着商场物品列表中新物品的增多。panel下加载的实例也非常庞大。而大部分的实例用户也无法看到&#x…

YOLOv5,YOLOv7改进之结合​SOCA

1.SOCA moudle结构图 2,YOLOv5,YOLOv7改进之结合​SOCA 1.配置common.py文件 #SOCA moudle 单幅图像超分辨率 class Covpool(Function):@staticmethoddef forward(ctx, input):x = inputbatchSize = x.data.shape[0]dim = x.data.shape[1]h = x.data.shape[2]w = x.data.sha…