zhouqijie

智能指针

CRE:智能指针在析构时会自动delete。防止了很多时候忘记delete或者因为抛出异常而错过了delete。(函数终止或者异常抛出时都会自动清除堆栈并析构局部对象变量,属于C++的特性)

三种智能指针的使用

避免两个指针指向同一个休想,因为可能导致程序删除一个对象两次的问题。

auto_ptr:一个特定对象只能一个智能指针拥有。赋值操作会转让所有权。
unique_ptr:比auto更加严格。
shared_ptr:智能更高的指针。能跟踪特定对象的引用计数。最后一个指针过期时自动调用delete








容器概述



迭代器(Iterator)

模板使得算法独立于存储的数据结构,而迭代器使算法独立于使用的容器类型。

  1. 输入迭代器。(程序<=容器)(不一定能让程序修改值)(不保证第二次遍历时候顺序不变)(不保证先前值能解引用)
  2. 输出迭代器。(程序=>容器)(能修改容器值,但是不能读取)
  3. 正向迭代器。(只能++单向迭代)(总是按照相同的顺序遍历)(递增后前面的迭代器值依然可以解引用)(可以使得能读能写,也可以使得只能读取)
  4. 双向迭代器。(具有正向迭代器所有特性,还支持递减)
  5. 随机访问迭代器。(可以随机访问例如使用索引[]

S::iterator (例如vector<Component *>::iterator it)

it++; //指向下一个元素,返回类型不确定。
++it; //指向下一个元素,返回it自身的引用。

迭代器是广义指针,而指针满足所有的迭代器要求。

在遍历map时候:(*it).first会得到key。(*it).second会得到value。



插入器(Inserter)

插入迭代器可以与STL算法(如std::copystd::transform等)一起使用,使得代码更加通用。你不需要知道目标容器的具体插入方法,只需要一个插入迭代器。

使用std::back_inserter创建一个std::back_insert_iterator,它会将元素插入到容器的末尾。(适用于支持push_back操作的容器)
使用std::front_inserter创建一个std::front_insert_iterator,它会将元素插入到容器的末尾。(适用于支持push_front操作的容器)
使用std::inserter创建一个std::insert_iterator,它会将元素插入到容器的末尾。(适用于支持insert操作的容器)



容器基本功能

begin()  //返回指向第一个容器的迭代器。
end()  //返回最后一个元素的下一个位置的迭代器。(即超过容器尾)

//begin       end
// |           |
//|1|2|3|4|5|6|

clear()  //清空。
empty()  //返回是否为空。
size()  //返回元素个数。(类型size_t)  


for_each(begin, end, func)//遍历  
random_shuffle(begin, end)//打乱  
sort()//排序


s1.swap(s2)  //交换s1和s2容器的内容。





Ⅰ、顺序容器(即序列Sequence)

常见的顺序容器有:动态数组vector<T>、双向链表list<>、双端队列deque<>、队列queue<>、优先队列priority_queue<>、栈stack<>等。
vector是顺序结构,list是链式结构。
vector/list存储的是值。所以用来存放对象时通常是存放指针。

CRE:C#中的List是顺序结构的,相当于C++的vector。

顺序容器方法

通用:

insert();  
erase();
clear();
front();  //含义: a.begin()
back();   //含义: --a.end()
push_back();  
push_front();  
pop_front();  
pop_back();  
[n];
at(t);  //含义同[n]

其他:

merge(x)//(list)  将调用链表与调用链表合并,两个链表必须已经排序。合并后的经过排序的链表保存在调用链表中。  
remove(val)//(list)  从链表删除val的所有示例。  
sort()
splice(it, x)//(list)  将链表x的内容插入到it前。   
push(); //(stack/queue) 栈顶或者队尾插入。  
pop(); //(stack/queue) 栈顶或者队首删除。  

插入元素

insert(); //插入元素。
※重载:s.insert(p1, t) //在p1所指位置插入新元素t,插入后的元素夹在原p1和p1-1所指元素之间。返回一个迭代器指向新插入元素。
※重载:s.insert(p1, n, t) //在p1所指位置插入n个新元素t,插入后的元素夹在原p1和p1-1所指元素之间。无返回值。
※重载:s.insert(p1, q1, q2) //将[q1,q2)区间内的元素顺序插入s容器的p1位置处,插入后的元素夹在原p1和p1-1所指元素之间。

删除元素

erase();
※重载:erase(p)和erase(b,e);第一个删除迭代器p所指向的元素,第二个删除迭代器b,e所标记的范围内的元素。
※补充:erase函数的返回值是一个指向被删除元素的下一个元素的迭代器。
使用示例:

for (vector<Component *>::iterator it = coms.begin(); it != coms.end();)
{
	if (*it == com1)
	{
		it = coms.erase(it);
	}
	else
	{
		it++;
	}
}
delete com1;

clear()全部清除,等价于erase(begin(), end())

Ⅱ、关联容器

CRE:关联容器可以理解为存储键值对的容器。

常见的关联容器:set<>multimap<>unordered_mapunordered_set等。

无序关联容器关联容器的区别是,关联容器是基于红黑树的,而无需关联容器基于哈希表,提高了添加和删除元素的速度以及提高查找算法的效率。



Map

map被定义为一对数值,即键值对(key-value pair)。字典就是map的一个不错实例。

按key查找value时,key不存在map中,这个key会自动加入map中并给与value默认值。(最好使用find()函数查询是否存在key)

任何一个key值在map中最多存在一份。如果需要存储多份相同的key值,就必须使用multimap。



Set

set由一群key组合而成。如果我们想知道某值是否存在于某个集合内,就可以使用set。

对于任何key值,set只能存储一份。如果要存储多份相同的key值,必须使用multiset。

(END)