STL的理解之list
STL的理解之list
1.list是底层是什么?
是双向指针实现的。
2.为什么要有list?
因为list不同于vector和string是由数组实现的,插入删除慢,随机访问快,所以设计出list,对于需要插入删除快,随机访问少的场景,list能很好的满足。
3.为什么list有迭代器类,而string vector没有?
因为list是链表,迭代器不能通过自增,自减来访问下一个结点,需要设计一个类,类里面进行各种操作的重载,使得list迭代器也可以++(实则就是 p = p -> next).
4.模板?
template
void Swap(T& rx, T& ry) {
T tmp = rx;
rx = ry;
ry = tmp;
}
5.typedef的几种用法?
变量的重命名
typedef int size ——> size a = 1;
数组的重命名
typedef int size[2] ——> size a 等价于 int a[2]
结构体的重命名
typedef struct stu
{
…
}STU STU 是 struct stu的别名 可以定义为 STU s1
指针的重命名
typedef char* size size a 等价于 char* a
6.list里的迭代器POS——>_year ,有几个 ——>? 为什么? 作用是什么?
有两个, 第一个的作用是取得Date*的指针,第二个的作用是取得Date里的_year,通常省略一个,只写一个——>
7.移动构造和移动赋值的作用?
没有c++ 11的移动构造和赋值之前, string类返回 分两种情况
一是 string s = xxx(返回的是string类的函数) 一次拷贝构造 一次拷贝构造
二是 string s ; s = xxx 一次拷贝构造 一次赋值构造
由于赋值构造复用了拷贝构造 所以一二都是两次拷贝构造
但当移动构造和赋值出来后,在返回string类时,由于要生成临时对象,它是右值,所以就调用了移动构造和赋值,但由于其底层实现是swap函数,是仅仅只是交换了资源,比拷贝构造和赋值使用的深拷贝代价小。
ps:有部分编译器会优化一 变成一次拷贝构造 如果是c++11 就是一次移动构造
而二,编译器对二这种情况无法优化 一次拷贝构造 一次赋值构造 有11就是一次移动构造 一次移动赋值。
8.const T& front() const
{
return *begin(); //返回第一个有效数据的const引用
} 为什么前后都要加const?
因为后面的const是确保在调用函数期间,成员变量不被修改
前面的const是确保,接收函数调用结果的变量也不能修改函数的成员变量。
9.resize reserve reverse?
前面两个是开空间的函数 后面一个是翻转函数。
10.list里中的resize如何实现的?
不调用size函数,而是设置一个变量ten while循环下和n比较, 如果大于n,则调用erase删除后面的结点。如果小于n,则调用push_back进行插入。
源代码:
void resize(size_t n, const T& val = T())
{
iterator i = begin(); //获取第一个有效数据的迭代器
size_t len = 0; //记录当前所遍历的数据个数
while (len < n&&i != end())
{
len++;
i++;
}
if (len == n) //说明容器当中的有效数据个数大于或是等于n
{
while (i != end()) //只保留前n个有效数据
{
i = erase(i); //每次删除后接收下一个数据的迭代器
}
}
else //说明容器当中的有效数据个数小于n
{
while (len < n) //尾插数据为val的结点,直到容器当中的有效数据个数为n
{
push_back(val);
len++;
}
}
}