【C ++】C++入门知识(二)

news2025/7/19 17:58:21

C++入门(二)

作者:小卢
专栏:《C++》
喜欢的话:世间因为少年的挺身而出,而更加瑰丽。 ——《人民日报》

1.引用

1.1.引用的概念及应用

引用(&)

引用不是新定义一个变量,而是给已存在变量取了一个别名

它和它引用的变量共用同一块内存空间

类型& 引用变量名(对象名) = 引用实体;

引用在定义时,必须初始化

一个变量可以多次引用

1.2.传值返回和传址返回和传引用返回的底层原理:

int Cout()
{
	int n = 0;
	n++;
	return n;
}
int main()
{
	int ret = Cout();
	return 0;
}

n是如何传给ret的呢?

因为这里的n没有用static修饰,为临时变量,Cout函数调用时开辟了一段栈帧,n存在于这段栈帧内。但函数调用结束后,栈帧销毁。

n可以传过去是因为,函数栈帧结束前用了一个临时变量=n,然后用这个临时变量来作为返回值给ret。

这个临时变量应该内存比较小的时候,是用寄存器。

int Cout()
{
	static int n = 0;
	n++;
	return n;
}
int main()
{
	int ret = Cout();
	return 0;
}

这种情况下,n在静态区,这里n还是用一个临时变量来作为中间段,来进行返回值。

这种情况有优化的空间:

这种返回类型为传值返回。那如果用传引用返回呢?

这种就是利用一些变量出了作用域过后还存在的情况,例如:引用,malloc…

int& Cout()
{
	static int n = 0;
	n++;
	return n;
}
int main()
{
	int ret = Cout();
	return 0;
}

引用返回的好处:
1.减少拷贝
2.调用者可以修改返回对象

//引用返回
//1.减少拷贝
//2.调用者可以修改返回对象
#define N 10
typedef struct Array
{
	int a[N];
	int size;
}AY;
int& PostAt(AY& ay, int i)
{
	assert(i < N);
	return ay.a[i];
}
int main()
{
	//int ret = Cout();
	AY ay;
	for (int i = 0; i < N; i++)
	{
		PostAt(ay, i) = i * 10;
	}
	for (int i = 0; i < N; i++)
	{
		cout << PostAt(ay, i) << " ";
	}
	cout << endl;
	return 0;
}
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;
	//ret为随机值
	return 0;
}

这里ret为随机值,这里c返回的是一个别名,相当于返回的是一个c的别名,ret就是c的别名。

int main()
{
	int a = 1;
	int& b = a;
	//指针和引用,赋值/初始化,权限可以缩小,但不可以放大
	const int c = 2;
	int& d = c;
	return 0;
}

指针和引用,赋值/初始化,权限可以缩小,但不可以放大

1.3.指针和引用的区别:

从语法角度:引用是不开辟空间的,指针需要开辟空间

从底层角度:两种都是一样的

2.内联函数

2.1.宏的缺点:

1.不能调试

2.没有类型安全的检查

3.有些场景下非常复杂

#define ADD(x,y) ((x)*(y))//正确的宏函数
	//宏不是传参,而是替换
#define ADD(x,y) (x)*(y)///((a | b)* (a & b)),错误
#define ADD(x,y) (x*y)///(5+10*6+20),错误
#define ADD(x,y) x*y
//5+10*6+20=85,错误,替换可能会造成运算过程出错
int main()
{
	ADD(1, 2);
	//宏不是传参,而是替换
	int a = 1, b = 2;
	ADD(a| b, a & b); ///(a | b* a & b)
	return 0;

}

这里宏是替换而不是传值,它不会检查替换的值,像(a | b+ a & b)就会错误

使用宏函数,需要尽量加括号,很容易错。

2.2.内联函数

inline int Add(int x, int y)
{
	int z = x + y;
	return z;
}
int main()
{
	int ret = Add(1, 2);
	cout << ret << endl;
	return 0;
}

在这里插入图片描述

release中没有call Add,减少了函数调用时栈帧的开辟

效率提高,并且可以调试,很好的替代了宏

inline内联函数是一种以空间换时间的情况,这里的空间指的是编译的指令,不是内存

// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
f(10);
return 0;
}

这里会出现链接错误:
在这里插入图片描述

内联函数不建议定义和实现分离!

当定义和实现分别在.c文件和.h文件中时:程序运行时,当程序运行时,main函数编译到f(10)的地方,会优先编译函数定义并不会链接,而在链接过程中,通过头文件找到函数调用

当f为内联函数时,内联函数是在编译过程完成编译的,因此系统就会认为f()是一个内联函数,所以不会将其链接,所以就会出现链接错误。

3.auto关键字

#include <iostream>
using namespace std;
int main()
{
	int a = 0;
	auto b = a;
	auto c = &a;
	//typeid(变量名).name()可以获取变量的实际类型
	cout << typeid(b).name() << endl;//int
	cout << typeid(c).name() << endl;//int*
	return 0;
}

3.1auto的好处

std::map<std::string, std::string>dict;
	std::map<std::string, std::string>dit=dict;
	//上一行和下一行是一样的,这就是auto的实际好处
	auto dit = dict.begin();

3.2typedef的缺点:

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

p1:实际上使用typedef后,const pstring p1会变成char* const p1

这里const修饰的是p1,而这样的p1只有一次初始化的机会,因此必须初始化。

4.范围for

自动依次取数组中数据赋值给e对象,自动判断结束

for循环后的括号由冒号“ :”分为两部分:

第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

int array[] = { 1,2,3,4,5,6,6,4 };
	for (int i = 0; i < sizeof(array) / sizeof(int); i++)
	{
		cout << array[i] << " ";
	}
	cout << endl;
	//范围for --语法糖
	for (auto e : array)
	{
		cout << e << " ";
	}//两种结果一样
	cout << endl;

5.nullptr

void f(int)
{
	cout << "f(int)" << endl;
}
void f(int*)
{
	cout << "f(int*)" << endl;
}//这里函数重载,但结果都是f(int)
//C++中,NULL被定义为0,这也不知道为什么是个错误不太好
int main()
{
	f(0);
	f(NULL);
	return 0;
}

因此,C++11中打了一个补丁,用nullptr来代替NULL。

注意:

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

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

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

相关文章

前缀和与差分---概念+例题

目录 前缀和 概念 例题 差分 概念 例题 前缀和 概念 在高中学习了数列的概念&#xff0c;跟现在的数组很像。可以类比来看&#xff0c;数组的前缀和与数列的前n项和其实可以看成一个概念。很多算法题利用前缀和的思想也就是可以使用高中里面的前n项和来求解数组里面任何…

3年功能测试经验,面试想拿到15k很难吗?

一直觉得经验多&#xff0c;无论在哪都能找到满意的工作&#xff0c;但是现实却是给我打了一个大巴掌&#xff01;事后也不会给糖的那种... 个人情况 大概介绍一下个人情况&#xff0c;男&#xff0c;本科&#xff0c;三年多测试工作经验&#xff0c;一毕业因为不成熟的经验以…

大型数据库Oracle12C 复习笔记

大型数据库Oracle1 Oracle基础1.1 Oracle基础概念1.2 Oracle体系结构1.3 多租户架构1.4 Oracle进程1.5 内存结构1.6 文件系统2 Oracle查询3 Oracle对象4 Oracle编程1 Oracle基础 与MySQL、MSSQL不同&#xff0c;Oracle数据库系统是美国ORACLE&#xff08;甲骨文&#xff09;公…

还在用chatGPT聊天?《元宇宙2086》已开始用AIGC做漫画连载了!

ChatGPT 是由 OpenAI开发的一个人工智能聊天机器人程序&#xff0c;于 2022 年 11 月推出。该程序使用基于 GPT-3.5架构的大型语言模型并通过强化学习进行训练。 ChatGPT 目前仍以文字方式互动&#xff0c;而除了可以透过人类自然对话方式进行交互&#xff0c;还可以用于相对复…

多线程使用哈希表

❣️关注专栏: JavaEE 多线程环境使用哈希表&#xff0c;HashMap 本身不是线程安全的. 在多线程环境下使用哈希表可以使用: Hashtable&#xff08;不推荐使用&#xff09;ConcurrentHashMap&#xff08;推荐&#xff09; &#x1f388;1 Hashtable Hashtable是线程安全的&am…

OpenGL中图片尺寸和上屏尺寸不一致的变形问题解决

一、尺寸不一致问题&#xff1a; 图片加载到OpenGL纹理&#xff0c;再将纹理进行上屏的时候&#xff0c;可能会出现图片尺寸和屏幕尺寸不一致&#xff0c;导致图片绘制到屏幕时出现变形的问题&#xff1a; 二、根本原因&#xff1a; 原始图片的纹理尺寸&#xff08;Textur…

计网之IP协议和以太网

文章目录一. IP协议1. IPv4报头介绍2. 解决IPv4地址不够用的问题3. IP地址管理4. 路由选择二. 以太网三. 浅谈DNS域名解析系统一. IP协议 IP协议是位于OSI模型中第三层(网络层)的协议, 在这层上工作的不止这一个协议, 但IP协议是网络层传输所使用的最主流的一种协议, 有IPv4和…

C语言——指针进阶

目录 前言 一. 字符指针 二. 指针数组 三. 数组指针 3.1 何为数组指针&#xff1f; 3.2 &数组名与数组名 四. 数组参数、指针参数 4.1 一维数组传参 4.2 二维数组传参 4.3 一级指针传参 4.4 二级指针传参 五. 函数指针 六. 函数指针数组 七. 指向函数指针数组…

Java 继承中构造函数的问题

继承中构造函数的问题 父类构造函数和子类构造函数的关系 new一个之类对象时默认调用了父类的无参构造函数 ,创建了父类对象 父类的成员变量和成员方法才能创建出来 子类才能继承下来使用 首先创建一个父类&#xff0c;动物类 接下来创建一个子类&#xff0c;狗类&#xff…

基于OSG的虚拟校园系统的设计与实现

基于open scene graph的虚拟校园系统的设计与实现 摘要 •引言 • OSG基本原理 •OSG操作与动画 •视点的定位和切换 •自由漫游 •路径漫游 • 路径动画 • 点选和文字 • 粒子系统 • 3DMAX • 无线通信与数据库设计 • 实现步骤 • 结论 摘要 随着科技的不断发展,人工智能&a…

2023年,8种必备Selenium编写自动化用例的技巧

在开始自动化时&#xff0c;您可能会遇到各种可能包含在自动化代码中的方法&#xff0c;技术&#xff0c;框架和工具。有时&#xff0c;与提供更好的灵活性或解决问题的更好方法相比&#xff0c;这种多功能性导致代码更加复杂。在编写自动化代码时&#xff0c;重要的是我们能够…

2023年网络安全十大发展趋势

近日&#xff0c;中国计算机学会&#xff08;CCF&#xff09;计算机安全专委会中来自国家网络安全主管部门、高校、科研院所、大型央企、民营企业的委员投票评选出2023年网络安全十大发展趋势。 趋势一 数据安全治理成为数字经济的基石 我国《数据安全法》提出“建立健全数据…

spring的启动过程(一) :IOC容器的启动过程

一、web容器的加载 首先我们要先知道一个web项目的启动过程。 将Web项目部署到Tomcat中的方法之一&#xff0c;是部署没有封装到WAR文件中的Web项目。要使用这一方法部署未打包的webapp目录&#xff0c;只要把我们的项目&#xff08;编译好的发布项目&#xff0c;非开发项目&am…

掌握MySQL分库分表(五)SpringBoot2+MybatisPlus整合Sharding-Jdbc水平分表实现

文章目录创建Java-Maven项目创建数据库、表创建Java实体类配置启动类水平分表配置文件配置测试分库分表实现分析控制台SQL逻辑SQL真实SQL主键重复问题创建Java-Maven项目 添加依赖 <properties><java.version>11</java.version><maven.compiler.source&…

PMP考试有没有什么技巧可以介绍一下么?

一、试题形式 ——中英文对照 即每道题都是一遍英文&#xff0c;一遍翻译的中文&#xff0c;在审题的时候有一些小的技巧需要注意。首先如果你的英文水平足够好&#xff0c;建议直接阅读原文。PMP试题毕竟是美国人出的&#xff0c;语言的组织、思想的表达&#xff0c;肯定更符…

python居然能语音控制电脑壁纸切换,只需60行代码

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 家在日常的电脑使用中&#xff0c;都会有自己喜爱类型的桌面 单纯的桌面有时候会让人觉得单调 今天&#xff0c;就由我带领大家只用60行代码打造一款语音壁纸切换器程序&#xff0c; 让大家能够通过语音的方式来控制电脑去…

c++模板的简单认识

文章目录 前言一.泛型编程 函数模板 模板参数的匹配原则 类模板总结前言 ADD函数很好写&#xff0c;但是如果我们要有int类型的&#xff0c;double类型的&#xff0c;char类型的等等各种类型&#xff0c;难道要写这么多不同的ADD函数吗&#xff0c;这么写简直太麻…

Linux:基于bufferevent epoll tcp服务器代码

基于bufferevent epoll tcp服务器代码: #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <event2/event.h> #include <event2/buffer…

Excel/Word的一些快捷操作整理

Excel/Word的一些快捷操作整理 1. 给Word文件导入目录 前提&#xff1a;大致内容已经定稿&#xff0c;文章中各标题分级明确&#xff0c;最好各级标题字体大小设置不一样。 步骤&#xff1a;在头部导航栏&#xff0c;选择**“引用”–“目录”**&#xff0c;根据自己需求选择其…

KDJB1200六相继电保护测试仪

一、概述 KDJB1200继电保护测试仪是在参照电力部颁发的《微机型继电保护试验装置技术条件(讨论稿)》的基础上&#xff0c;广泛听取用户意见&#xff0c;总结目前国内同类产品优缺点&#xff0c;充分使用现代新的的微电子技术和器件实现的一种新型小型化微机继电保护测试仪。可…