一、重载函数部分
①对于重载函数来说,不允许两个函数参数列表相同但返回类型不同,这种情况下第二个函数的声明是错误的;
②候选函数和可行函数:
·在调用重载函数时,集合中的函数被称为候选函数,具备的特征包括:与被调函数同名、其声明在调用点可见;
·第二步检查本次调用提供的实参,可行函数也有两个特征:一是其形参数量与本次调用提供的实参数量相等、而且每个实参的类型与对应的形参类型相同,或者能转换成对应的形参类型;
③二义性调用:是一种编译时发生的错误,造成的原因是在函数匹配时两个或多个函数的匹配性一样好,编译器找不到唯一的最佳匹配。
二、类
①类的构造函数中,可以先定义,再赋值,也可以直接初始化。一般情况下使用两种方式进行初始化都可以,但如果涉及和考虑到底层效率的优化,就要使用直接初始化的方法;
②如果没有给类定义构造函数,在定义类的时候会调用系统给的默认构造函数。这样的话定义时应该是ClassName c,而不是ClassName c(),后者是声明了一个函数;
③编译器只会执行一步类型转换,如果涉及到两步的类型转换,就需要把其中的一步显式地写出来,否则会报错;
④聚合类:用户可以直接访问其成员,并且具有特殊的初始化语法形式。当一个类满足以下条件时,我们说它是聚合的:
·所有成员都是public的;
·没有定义任何构造函数;
·没有类内初始值;
·没有基类,也没有virtual函数。
⑤类的静态成员:有的时候我们需要一些成员与类保持联系,而不是与类的每个对象都保持联系。例如银行账户类中的利率,我们不需要让每个银行账户对象都存储利率这一变量,只需要利率和银行账户这个类关联,而且也希望所有对象中的利率同步更新,此时就需要把利率这一变量设置成类的静态成员(在成员前加上static);
⑥因为静态数据成员不属于类的任何一个对象,所以它们并不是在创建类的对象时被定义的,这意味着它们不是由类的构造函数初始化的。而且一般来说,我们不能在类的内部初始化静态成员。必须在类的外部定义和初始化每个静态成员,一个静态数据成员只能定义一次。
三、IO库
①IO输入输出机制是通过继承机制来实现不同类型的流的输入输出的,string类型的输入是继承于istream,因此对于使用标准库中IO机制的用户来说,可以用同一种方式对不同类型的变量进行输入输出;
②读取文件:先用ifstream file(“路径”)打开文件,然后用is_open判断是否打开。在读取操作中,分为三种:逐行分词读取、逐行不分单词读取、逐次读取:
·逐行分单词读取:用char数组,while(file.getline(tmp,100));
·逐行不分单词读取:用string,while(getline(file,tmp));
·逐词读取:用string,while(file >> tmp)。
③ofstream用上,较类似,在实现一些细节功能能的时候可以再学。
四、顺序容器
①选择容器的基本原则:
·除非有很好的理由选择其他容器,否则使用vector;
·如果程序有很多小的元素,且空间的额外开销很重要,则不要使用list和forward_list;
·如果程序要求随机访问元素,应使用vector或deque;
·如果程序要求在容器的中间插入或删除元素,应使用list或forward_list;
·如果程序需要在头尾位置插入或删除元素,但不会在中间插入或删除,则使用deque;
·如果程序只有在读取输入时才需要在容器中间插入元素,随后需要随机访问元素,则:首先确定是否真的需要在容器中间位置添加元素,因为如果直接添加,再排序可以解决问题的话,就不属于要在中间位置添加元素情况;其次,如果确定必须要在中间位置插入,可以考虑在输入阶段使用list,输入完成后,将list中的内容拷贝到一个vector中。
②向一个vector、string或deque插入元素,如果存储空间重新分配了,会使所有指向容器的迭代器、引用、指针失效;否则,指向插入位置之前的迭代器有效,插入位置之后的迭代器失效。这个很好理解,迭代器本来就是来选择位置的,你插入元素不会影响这个位置之前的迭代器;
③除了push_back操作,list、forward_list和deque还支持push_front,即把元素插入到容器前面;
④insert函数:可以利用迭代器,将想要插入的元素插入到迭代器当前位置的前一个位置(因为迭代器的end是遍历到末尾元素的后一个位置,因此插入到当前迭代器的下一个位置是不安全的,如果当前迭代器遍历到end,下一个位置是越界的。相反,插入到前面则不会出现这个问题,因为begin指向的是第一个位置);
⑤emplace操作:emplace_front、emplace和emplace__back,分别对应前插、插入和后插操作。与push_back不同的是,emplace_back是在容器管理的内存空间中直接创建对象,而push_back是创建一个局部临时对象,并将其压入容器中。正因为emplace_back是在内存中直接创建,不会被经过任何处理,因此其输入必须与容器元素类型相匹配;
⑥如果要用迭代器进行操作的话,在循环中也要注意更新迭代器;
⑦size和capacity不一样,size是当前容器中的元素数量,capacity是当前分配给该容器的大小,即最多能装多少个元素。当size大于capacity时,就会重新分配空间了;
⑧修改string操作:insert、erase、assign/replace、append(在尾部添加)。
五、泛型算法
①标准库并未给每个容器添加大量功能,而是提供了一组算法,这些算法中的大多数都独立于特定的容器,是通用的,因此这些算法被被称为泛型算法;
②一般情况下,泛型算法都不直接操作容器,而是遍历由两个迭代器指定的由一个元素范围来进行操作;
③迭代器令算法不依赖于容器,但算法的操作依赖于元素类型;
④一些算法需要从两个容器序列中拿元素,这时候不要求两个容器类型相同,只要两个容器内的元素类型之间能进行比较即可;
⑤vector容器的去重操作:先用sort函数排序,然后用unique(删除相邻的重复项,因此需要先sort)重排输入范围,使得重复的元素都排到后面,返回的是不重复区域后一个位置的迭代器,意思就是这个迭代器后面的都是筛选出来的重复元素,然后用erase函数删除此迭代器到end的所有元素即可。经实验确实可以,牛;
⑥默认情况下,重排元素的算法都是在原来的容器中进行排列,这些算法还提供了另一个版本,将元素写到一个指定的输出位置,例如反转算法:
reverse(beg,end); //反转容器中的元素;
reverse_copy(beg,end,tmp); //将元素按逆序拷贝到tmp里;
⑦lambda表达式:是可调用的代码单元。一个lambda类似一个未命名的内联函数。一个lambda以一个捕获列表开始,此列表允许lambda访问函数中的变量。类似函数,lambda有一个参数列表,一个返回类型和一个函数体。lambda可以忽略返回类型,如果函数体是一个单一的return语句,返回类型就从返回对象的类型推断。否则,忽略的返回类型默认为void。(lambda表达式的内容还挺多的,以后用的时候需要再细细地学一遍)。
关联容器放到下次,还比较重要,不能水过去。