模板一定要用<类型>实例化。
用谁实例化模板。函数模板。
绑定器和取反器。
成败都在细节,全国性的秋招,每个层次的人都很多。
思想太害怕了。
容器迭代器,函数模板,
c++到最后就是各种各样的封装。
template<typename Iterator1,typename Iterator2>
void mycopy(Iterator1 first,Iterator1 last,Iterator2 dest)//把两个指针指向的内存拷贝到另外两个指针指向的内存中。
{
while (first != last)
{
*dest = *first;
++first;
++dest;
}
}
不是所有迭代器都有[]运算符重载函数。如果是链表就不会给提供[]运算符重载函数。
迭代器没有提供后置++运算符重载函数。
通过容器的begin和end函数。
给vector添加元素只有两种方法push_back(尾插元素)和insert(按位置插入元素)
容器支持push_front 、push_back、insert。
迭代器:正向迭代器、反向迭代器(从后往前遍历)、插入型迭代器(可以通过迭代器给容器添加元素)
iterator vec.begin() vec.end()
都是用于泛型算法。
#include <iterator>//迭代器的头文件。STL
后插型迭代器,只能在容器后面插入。
赋值运算符重载函数。
可以使用多层的typedef。
c++的封装性,给一个东西一封装就变成了一个新的东西。
凡事多问问为什么,有哪些应用场景。
template<typename Container> class _myback_inserter { public: typedef typename Container::value_type T; _myback_inserter(Container &con) :_con(con){} _myback_inserter<Container>& operator*(){ return *this; } _myback_inserter<Container>& operator=(const T &val) { _con.push_back(val); return *this; } _myback_inserter<Container>& operator++(){ return *this; } private: Container &_con; }; template<typename Container> _myback_inserter<Container> myback_inserter(Container &con) { return _myback_inserter<Container>(con); }
运算符重载屏蔽了一切的细节。
只要有容器就有迭代器。
迭代器的操作时很强大的,迭代器实际上也是对cout进行了一下封装。
输入也是一个容器(数组),也可以使用迭代器去迭代它。
插入型迭代器。
善于使用c++的容器迭代器可以大大减少代码量,提高代码的强劲性。
跟比较相关的都是二元函数模板。用绑定器绑定一下。
c++ STL
很多算法都在泛型算法里面做完了。
STL容器
顺序容器
vector:向量容器
deque:双向队列容器(双端队列容器)
list:双向链表容器
容器适配器
stack:栈
queue:队列
priorit_queue:优先级队列
/*******************************/
多少个日日夜夜,开发人员才把源码弄出来。
c++的源代码不好看,要看的话就看vc的源码。不要看vs的源码。
稳健的库。
按值删除,按迭代器删除。
vector底层的内存时连续的。适合二分查找。
list底层的数据结构是链表,适合插入删除。
reserve解决vector容器初始操作效率低的问题,它会首先预留一定的空间(开辟好的),返回元素个数为0.
list容器特有的数据结构:双向链表。
链表的所有元素地址不是连续的。
不涉及对象的构造析构,操作效率相当高。不涉及任何内存开辟释放,对象构造析构。
其实就是用类把链表封装了一下,但是人家提供了迭代器,操作起来非常方便。
以后写代码,遇到数组就使用vector。链表就使用list。没有人会从零开始造轮子。
二维数组的开辟:1.先开辟一维数组,再开辟二维数组,空间上不连续。
2.直接开辟二维数组,地址连续。
list不涉及内存的增长。
deque:双向队列容器(双端队列容器):内存不连续,是动态开辟的。
作业:大数的加减法操作。
提供一个输出运算符重载函数。
加法都是从个位数开始加的。
并且把三个顺序容器搞清楚,下去休息一下就赶紧写,不然时间长了就都忘完了。