目录
【前言】
接上一篇没有写完的c++基础入门,并且新增了数据结构初阶
1.const引用
这里const引用的对象,涉及到“权限”的问题,下面看3个例子:
在这里有一个前提知识:权限只可以缩小,不可以放大
1.第一个代码,int &ra=a;不可以的原因就是因为他将权限放大了(想一下,ra是a的别名,那变量a前面都加了const,说名变量a不让修改,那么ra作为a的别名,ra更不可以被修改了)可以这么想,a这个本尊都修炼不成的功法,你ra作为本尊的替身(分身)更别想修炼成了。所以这里在前面加一个const即可很好的解决问题!(使两个都不可以被改变即可)
2.第二个代码,就是权限缩小了(const int&rb=b;)当然你写(int &rb=b)也是可以的,第一个相当于权限缩小了(因为本尊a前面没有const,而rb前面有了const,对rb做了一个限制)。第二个,即权限不缩小也不放大,当然也是可以的。
3.第三个代码,是“类型转换的时候,是会有一个临时对象的”,从double类型转换成int类型,你若是(int&rd=d;)这样写,会涉及到权限放大的问题。因为,从d转换到rd,其实是先存到一个临时对象中,临时对象再转到rb中,(所以这里相当于引用的是临时变量)而临时对象具有常性,所以得在前面加上const修饰,否则就有权限放大的问题。
2.内联函数--inline
⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内联函数就不需要建⽴栈帧了,就可以提⾼效率。
一般c++编译器在调用函数的时候,都会有call,Add,jump(再jump回这个函数),那么jump之前的动作就是为调用这个函数开辟了栈帧(这些都是可以通过反汇编去观察到的,只不过因为博主能力不足,无法编写一个函数,让反汇编可以很好的去实现,若有哪位大佬可以的话,还请私信博主,谢谢!)。而内联函数在调用的时候,
在调用的地方直接展开内联,省去了开辟栈帧所需的空间。这样做就可以节省很多时间跟空间(可能一个函数看不出来什么,但是若是频繁调用某一个小函数,这作用可就很大了)。
但是使用内联函数需要注意以下几点:
1.内联函数展不展开,看编译器,所以请把你的代码放心的交给编译器吧!
2.inline要把声明跟定义放在同一个文件中,否则,内联的时候,只看到了函数的声明,找不到函数体,就无法内联。分开放还可能导致链接错误或者未定义行为!
3.内联函数适合用于那种短小并且频繁调用的函数。
4.之后博主将会介绍到类,在类中的成员函数都默认是内联函数,但建议遵循第三条,即将那种频繁调用且短小的函数放到成员函数中。
3.nullptr
在c语言中,null指的是什么?指的有两层意思。1.就是整数0. 2.是一个指针(void*)0。这将会导致什么问题呢?
第一个k函数调用的是整数0,所以打印的没有毛病,但是!第二个呢?我本意是想让k函数调用指针,打印(void k(int*y))但实际呢?并没有如我所愿,所以咱们的c++之父为了解决c语言的这个问题,引入了nullptr。
那么这个nullptr在某些程度上可以代替NULL,就比如空指针,以后咱们在c++的编程中,初始化指针并置为空,就可以使用nullptr,不用再使用NULL了!
【c++入门收尾】
OK啊,各位博友们,到这里c++基础入门算是彻底的讲完了,以后还会更新c++后续内容。那么到现在咱们再回去看第一个c++程序,是不是就茅塞顿开了呢?哈哈哈哈哈,以各位博友们的智慧,相信是轻轻松松的了。
4.数据结构入门--复杂度
复杂度呢又分为时间复杂度与空间复杂度,在这里咱们重点讨论时间复杂度。
咱们在写算法题目,或者一个代码的时候,都会面临着一个问题,就是这个算法好不好呢?看一个代码好不好,之前确实有人提了出来方法,但是呢,那个方法是在算法执行过程中才可以观察到---嘶,不好。于是呢,又经过了人们的挖掘,发明了可以在算法执行之前就可以看出这个算法好坏的方法,就是复杂度。
【时间复杂度】
【注:上面的图片选自《大话数据结构》这本书】
咱们来看两种算法,很明显可以看出第一种算法,有循环,而第二种算法并没有循环,所以第一种算法执行的次数是不是就多呀。而第二种算法执行的次数是不是就几次呀,很明显的比第一种算法执行次数要少很多,这些消耗的都是时间呀!肯定是循环次数越少,消耗的时间越好,这个算法也就越好。
有了循环次数越少,时间消耗越少,算法越好的原则,这就是时间复杂度的本质。
那么咱们接下来看一下时间复杂度的推导:
1.时间复杂度函数T(N)中,只保留最高阶项(相对而言)。例如:n^3+n^2,只保留最高项,所以就是n^3.
2.若最高阶项存在且其系数不是1,那么咱们可以去掉这个项的常数系数。例如:n与2n,当n越来越大时,他俩的差别并不是很大,所以他俩是同阶。所以,就是n
3.若T(N)中没有N相关的项,只有常数项,用常数1取代所有的加法常数。例如:上面图片的第二种算法的时间复杂度就是O(1)。
时间复杂度的写法就是O()括号里面写时间复杂度,(注意,这个时间复杂度只是一个相对模糊的概念,并不要求准确的)。
而且,一般,若没有特殊指明,时间复杂度指的是最坏的时间复杂度(因为你一个算法不可能每次时间复杂度都是最好,肯定是置于最好的与最坏的之间)。
那么最后来看看时间复杂度的排行图吧。
【注:上面的图片选自《大话数据结构》这本书】
【空间复杂度】
算的是变量的个数。
函数在运行时所需要的栈空间(存储参数,局部变量,一些寄存器等)在编译期间已经确定好了。因此空间复杂度就是通过函数在运行期间显式申请的额外空间来确定。
显式:直接占用的可直观看到的空间资源,比如:基本数据类型和基本类型变量,数组和容器,对象实例(在c++类和对象中会讲解)
比如 int arr[numsize],空间复杂度为O(n),像这个就是额外申请了空间。
注意:在很多算法中,会采用空间换时间的方法!这也是为了优化时间复杂度
OK啦,这期内容就到这了,咱们下期见面!