C++入门知识点总结(下篇·初学必看)

news2024/11/16 2:23:23

前言:Hello大家好😘,我是心跳sy,这篇文章将介绍下篇知识点内容,本系列文章将会更新关于C++的全部初阶以及进阶的知识点,喜欢的小伙伴点个关注不迷路哦~我们一起来看看吧~ 

 

目录

一、引用 💫

1.1、⭐️概念理解⭐️

1.2、⭐️引用要点及特性⭐️

1.3、⭐️常引用⭐️

1.4、⭐️使用场景⭐️

1.5、⭐️指针和引用的区别⭐️

二、内联函数 💫

2.1、⭐️什么是内联函数?⭐️

2.2、⭐️使用方法⭐️ 

2.3、⭐️函数特性⭐️ 

三、auto关键字 💫

四、基于范围的for循环 💫

4.1、⭐️什么是范围 for 循环⭐️

4.2、⭐️范围 for 循环的使用条件⭐️

五、指针空值(nullptr)💫 


 🌈心跳sy的C语言专栏  ⏪C语言知识点汇总到这了,有兴趣的友友可以订阅看看哟~💞💞💞

一、引用 💫

1.1、⭐️概念理解⭐️

🔶引用不是新定义一个变量,而是给已存在变量取了一个别名编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。

🔶用法:

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

void Test()
{
    int a = 10;
    int& ra = a;//定义引用类型
    printf("%p\n", &a);
    printf("%p\n", &ra);
}
int main()
{
    Test();//两个地址相同
    return 0;
}

 

👉上面例子给变量 a 起了个别名 ra,ra 和 a 共用一块内存空间,所以输出两个地址是一样的。

🔴注意:引用类型必须和引用实体是同种类型的

1.2、⭐️引用要点及特性⭐️

🔸1. 引用在定义时必须初始化

int& ra;//错误!引用必须初始化

int a = 10;
int& ra = a;//正确,编译通过

🔸2. 一个变量可以有多个引用,同时也可以给别名起别名,多个引用别名都指的是原变量

 int a = 10;
 int& ra = a;
 int& rra= a;

🔸3. 引用一旦引用一个实体,再不能引用其他实体

👉在C++中,引用一旦被初始化为指向某个实体(对象),就不能再改变它所引用的对象。这与指针有所不同,指针可以在任何时候改变其指向的目标。

int a = 10;
int b = 20;
int& ref = a;  // ref引用a
// 尝试改变ref的引用目标是不允许的
// int& ref = b;  // 错误:引用必须在定义时初始化

1.3、⭐️常引用⭐️

🔶C++中的常引用(const&)是一种特殊的引用类型,它为变量提供了 const 语义,即通过常引用修改变量的值是被禁止的;常引用在函数参数传递、返回值以及成员函数中经常被使用,以确保数据的不可变性,同时避免因复制大型对象而带来的性能开销。

const 类型& 常引用名;
//定义一个常引用
int a = 10;
const int& ref = a;

👉在上面的例子中,ref 是 a 的常引用,你不能通过 ref 修改 a 的值。 

1.4、⭐️使用场景⭐️

⭕️1、做参数

🔸使用引用作为函数参数,可以让函数修改传入的变量或者避免对大型对象的拷贝,提高效率。

void Swap(int& left, int& right)
{
   int temp = left;
   left = right;
   right = temp;
}

🔸例如交换变量的值,增加或减少变量的值都可以用引用,起作用效果和指针一样。

⭕️2、做返回值

int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n;
}

🔴需要特别注意,返回变量出了函数作用域就生命周期到了需要销毁(局部变量),不能用引用返回;也就是,如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用 引用返回,如果已经还给系统了,则必须使用传值返回;全局变量/静态变量/堆上变量就可以用引用返回,如上例。

1.5、⭐️指针和引用的区别⭐️

🔶指针和引用的功能是类似的,重叠的

🔶C++的引用,可以对指针使用比较复杂的场最进行一些替换,让代码更简单易懂,但是不能完全替代指针;引用不能完全替代指针原因:引用定义后,不能改变指向(比如链表指向)

🍀区别:

🔸引用概念上定义一个变量的别名,指针存储一个变量地址 

🔸引用是别名,不开空间,指针是地址,需要开空间存地址

🔸引用必须初始化,指针可以初始化也可以不初始化

🔸引用不能改变指向,指针可以

🔸引用相对更安全,没有空引用,但是有空指针,容易出现野指针,但是不容易出现野用

🔸sizeof(引用结果为引用类型的大小,但指针始终是地址空间所占字节个数,32 位平台下占4个字节)、++(引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小)、解引用(访问实体方式不同,指针需要显式解引用,引用编译器自己处理)访问等方面的区别。

🔶底层:

汇编层面上,没有引用,都是指针,引用编译后也转换成指针了
 

二、内联函数 💫

2.1、⭐️什么是内联函数?⭐️

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

👉面对这样一个场景:一个函数需要被不断调用100w次,建立100w个栈帧

c语言如何解决这个问题的?比如Add函数,需要建立宏函数#define ADD(a, b) ((a)+(b))

🔴注意括号控制优先级(当传参有表达式时) 

宏的缺点:

1、语法复杂,坑很多,不容易控制

2、不能调试

3、没有类型安全的检查

🔶在C++中就使用了内联函数同样解决了上面场景的问题,在编译时会把函数调用处用函数体来进行替换,这样就避免了上述的函数调用开销,大大提高了执行效率。

2.2、⭐️使用方法⭐️ 

🔶通过在函数声明或定义前加上 inline 关键字来建议编译器将这个函数作为内联函数处理。

inline int Add(int a, int b)
{
	return a + b;
}

2.3、⭐️函数特性⭐️ 

🔸1. inline 是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率;

🔸2. inline 对于编译器而言只是一个建议,不同编译器关于 inline 实现机制可能不同;

🔸3. inline 不建议声明和定义分离,分离会导致链接错误。因为 inline 被展开,就没有函数地址了,链接就会找不到。

三、auto关键字 💫

🔶C++11引入了 auto 关键字,这个特性被称为“自动类型推导”。

🔶1、auto 关键字的优点是可以让编译器根据变量初始化表达式自动推导变量的类型,从而简化代码。

auto i = 1; // i的类型被推导为int
auto d = 1.1; // d的类型被推导为double
auto s = "hello"; // s的类型被推导为const char*
​int i = 0;
int j = i;
auto k = i;
auto p1 = &i;//auto声明指针类型
auto* p2 = &i;//auto声明指针类型
auto& r = i;//auto声明引用类型

​
int TestAuto()
{
	return 10;
}
int main()
{
	int a = 10;
	auto b = a;
	auto c = 'a';
	auto d = TestAuto();
	cout << typeid(b).name() << endl;
	cout << typeid(c).name() << endl;
	cout << typeid(d).name() << endl;
	return 0;
}

👉识别b、c、d的类型名称如图: 

 

🔶在C++中,typeid 是一个运算符,它可以用来获取一个变量或表达式的数据类型。它的 name() 方法返回一个 const char*表示类型的名称(具体字符串依赖于实现,有可能不易读或者加密处理)。 

🔶2、auto 关键字还可以自动识别返回值,但注意 auto不能作为函数的参数。

auto add(int a, int b) 
{
    return a + b;
}

🔴注意:使用 auto 关键字必须初始化,在编译阶段编译器需要根据初始化表达式来推导 auto 的实际类型。因此 auto 并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将 auto替换为变量实际的类型。例如不能这样写:

 auto x;//错误

🔶3、auto 关键字也同样具有缺点,就是如果连续使用auto来自动识别变量,容易使其他看不清变量的类型,造成混淆,使用时尽量不要大量使用。

四、基于范围的for循环 💫

4.1、⭐️什么是范围 for 循环⭐️

🔶在C语言中我们学过 for循环,并会使用 for循环进行数组的修改和读取;在C++中有一种更方便快捷的数组修改和读取的方法,就是范围for循环。

🔶在C++11中引入了基于范围的 for循环。for 循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量(常使用 auto 关键字,自动识别变量类型更方便),第二部分则表示被迭代的范围。

👉看一下与正常遍历数组的对比:

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

	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
		array[i] *= 2;

	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
		cout << *p << endl;

	// C++11
	// 依次取数组中值赋值给e,自动迭代,自动判断结束
	
	for (auto e : array)
	{
		cout << e << " ";
	}
	cout << endl;

	return 0;
}

 

🍀使用范围for修改数组数值:

for (auto& e : array)
{
	e *= 2;
}
cout << endl;

🔴注意需使用引用来保证值可以被修改完成。

4.2、⭐️范围 for 循环的使用条件⭐️

🔸1. 范围 for 循环迭代的范围必须是确定的,对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供 begin和end的方法,begin 和 end就是for循环迭代的范围。

注意:以下代码就有问题,因为for的范围不确定

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

🔸2. 迭代的对象要实现++和==的操作。(涉及迭代器这个问题,我们以后会介绍) 

五、指针空值(nullptr)💫 

❓在之前的C++版本中曾出现了一个bug,就是关于NULL的问题,它究竟是一个字面量?还是一个空指针呢? 当我们在需要使用表示空值的指针时能不能使用NULL呢?来看看下面的验证:

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的确只是一个字面量,这就导致了在使用空值的指针时,都不可避免的会遇到一些不确定的麻烦,为了解决这个问题,C++定义了nullptr关键字,如下:

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

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

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

 

👉可以看到在使用 nullptr 来表示空指针时,不会造成区分不开的问题,我们建议以后都使用它来代表空指针。

本文到此结束💞💞💞感谢大家花费宝贵的时间阅读本文章,制作不易,希望大家多多支持呀😘😘😘,如有任何问题欢迎各位大佬在评论区批评指正!!!

 

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

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

相关文章

SAP 如何通过程序创建一个请求

一&#xff1a;首先我们需要知道SAP的资源类型 PGMID &#xff1a;程序ID OBJECT &#xff1a;对象类型 OBJ_NAME&#xff1a;对象名称 SY-REPID 我们可以通过SE09/SE10来创建一个请求号也能看的出来 也可以通过SE03来查找 请求号相关的数据都在E07*的表里这边…

IP 地址分类

IP 地址有两个版本&#xff1a; IPv4 和 IPv6 &#xff0c;目前使用最广泛的还是 IPv4 &#xff0c; IPv6 出现的目的主要是解决 IPv4 地址耗尽的问题。为了方便起见&#xff0c;在这里我们说的 IP 地址主要是指 IPv4 地址。 IP 地址是由 32 位比特组成&#xff0c;比如这个地…

初步认识二叉树

二叉树的概念及结构 二叉树在我们的想象中长这样 下图是满二叉树 二叉树有左右子树 1是根结点&#xff0c; 1的左子树是2&#xff0c;右子树是3&#xff1b; 2是根结点&#xff0c; 2的左子树是4&#xff0c;右子树是5&#xff1b; 3是根结点&#xff0c; 3的左子树是6…

odoo17 精减设置模块

odoo17 精减设置模块 设置模块中好多平时用不到的功能&#xff0c;如何隐藏&#xff0c;采取了继承修改方式&#xff0c;代码如下: <?xml version"1.0" encoding"utf-8" ?> <odoo><record id"resconfig_ex_form" model"i…

《人工智能商》:谁掌握了人工智能时代的思考方式,谁就掌握了未来

文/石墨杨&#xff08;shimoyang11&#xff09; 在可以预见的未来&#xff0c;马路上行驶着自动驾驶的汽车&#xff0c;工厂里忙碌着不知疲倦的机器人&#xff0c;网络电商会精准推荐你需要的商品&#xff0c;社交网站自动帮你识别令你心仪的朋友…… 《人工智能商》一书&#…

穿黑风衣的牛奶--生产问题之CompletableFuture默认线程池踩坑,请务必自定义线程池

前言 先说结论&#xff0c;没兴趣了解原因的可以只看此处的结论 CompletableFuture是否使用默认线程池的依据&#xff0c;和机器的CPU核心数有关。当CPU核心数-1大于1时&#xff0c;才会使用默认的线程池&#xff0c;否则将会为每个CompletableFuture的任务创建一个新线程去执…

代码随想录算法(哈希表二)

目录 454四数相加 15三数之和 双指针法 18四数之和 剪枝操作 454四数相加 暴力操作就是四个for循环 这个题目是用哈希表来解答 我们可以将ab进行一个遍历放到一个数组里面 再将cd来放到一个数组中 来看一下是否cd中有ab所需要的值 由于这个题目是int这种 所以只能从set 和…

vue中怎么自定义组件

目录 一&#xff1a;功能描述 二&#xff1a;实现过程 一&#xff1a;功能描述 在开发过程中我们经常需要自定义组件完成特定的功能&#xff0c;比如用户详情页&#xff0c;我增加一个调整余额的按钮&#xff0c;点击以后需要打开一个调整余额对话框&#xff0c;输入调整的金…

Babel 7入门基础知识 全面 实践案例篇【1】推荐。

babel前面我们梳理总结 webpack入门基础知识的时候已经用过了。趁着这个机会顺便把Babel基础知识回顾梳理一下&#xff0c;也欢迎正在使用babel的同学一起交流探讨&#xff0c;感谢。 目录 一、Babel是什么&#xff1f; 二、.Babel是如何工作的呢&#xff1f;或者原理是什么…

Windos 执行.sh文件提示没有足够权限执行的解决办法

找到Git安装目录下的sh.exe文件 右键以管理员方式运行 cd到.sh文件所在目录&#xff0c;注意使用 / 而不是 \ 执行.sh文件即可

JavaScript中闭包的概念与其造成的性能问题

如果一个函数没有访问任何外部作用域的变量或方法&#xff0c;那么它其实是拥有闭包特性的&#xff0c;因为在 JavaScript 中&#xff0c;每个函数都可以理解为对其创建时所处作用域的引用。从这个角度来说&#xff0c;即使普通函数本身并没有捕获外部变量&#xff0c;但它们仍…

JAVA集中学习第四周学习记录(四)

系列文章目录 第一章 JAVA集中学习第一周学习记录(一) 第二章 JAVA集中学习第一周项目实践 第三章 JAVA集中学习第一周学习记录(二) 第四章 JAVA集中学习第一周课后习题 第五章 JAVA集中学习第二周学习记录(一) 第六章 JAVA集中学习第二周项目实践 第七章 JAVA集中学习第二周学…

WPF篇(9)-CheckBox复选框+RadioButton单选框+RepeatButton重复按钮

CheckBox复选框 CheckBox继承于ToggleButton&#xff0c;而ToggleButton继承于ButtonBase基类。 案例 前端代码 <StackPanel Orientation"Horizontal" HorizontalAlignment"Center" VerticalAlignment"Center"><TextBlock Text"…

Redis的过期策略与内存淘汰机制详解

文章目录 Redis的过期策略1. 定时删除2. 惰性删除3. 定期删除 Redis的内存淘汰机制1. noeviction2. volatile-random3. volatile-ttl4. volatile-lru5. volatile-lfu6. allkeys-random7. allkeys-lru8. allkeys-lfu LRU与LFU算法总结 Redis作为一种高性能的键值对存储系统&…

C语言 之 理解指针(9)与指针相关的理解题

文章目录 代码1代码2代码3代码4代码5代码6代码7 本篇内容接上一篇&#xff0c;对指针进行一个更深入的理解 建议没看过 上一篇的可以看看上一篇&#xff0c;当然不看也可以。 建议先自行完成再看答案哟 代码1 #include <stdio.h> int main() {int a[5] { 1, 2, 3, 4, …

B站千亿级点赞系统服务架构设计

B站千亿级点赞系统服务架构设计 原文链接&#xff1a;https://www.bilibili.com/read/cv21576373/ 原文作者&#xff1a;哔哩哔哩技术团队-芦文超 点赞的功能太过于简单不再赘述&#xff0c;大家可以点击原文链接简单看下便可知晓。 本讲结合B站知名UP主陆总监的一期视频(h…

【vue3|第21期】Vue3中Vue Router的push和replace方法详解

日期&#xff1a;2024年8月9日 作者&#xff1a;Commas 签名&#xff1a;(ง •_•)ง 积跬步以致千里,积小流以成江海…… 注释&#xff1a;如果您觉得有所帮助&#xff0c;帮忙点个赞&#xff0c;也可以关注我&#xff0c;我们一起成长&#xff1b;如果有不对的地方&#xff…

Android系统Android.bp文件详解

文章目录 1. 基本语法结构2. 常见模块类型3. 模块属性常见属性包括&#xff1a; 4. 具体示例5. 高级功能5.1. 条件编译5.2. 变量定义与使用5.3. 模块继承 6. 总结 Android.bp 是 Android 构建系统&#xff08;Android Build System&#xff09;中的配置文件&#xff0c;用于描述…

C语言典型例题31

《C程序设计教程&#xff08;第四版&#xff09;——谭浩强》 习题2.8 请编写程序将China译为密码&#xff0c;密码的规律是&#xff1a;用原来字母后面的第4个字母代替原来的字母。 例如:C后面的4个字母是G&#xff0c;h后面第4个字母为l 代码&#xff1a; //《C程序设计教程…

TinyLLaVA: A Framework of Small-scale Large Multimodal Models

发表时间&#xff1a;22 Feb 2024 论文链接&#xff1a;https://arxiv.org/pdf/2402.14289 作者单位&#xff1a;SKLCCSE, Institute of Artificial Intelligence, Beihang University, Beijing, China Motivation&#xff1a;当前的大语言模型的参数量太大了&#xff0c;作…