In-depth analysis of common containers in C++ STL

Here we do not involve the basic operations of containers and so on, just to discuss the characteristics of each container. Commonly used containers in STL include: sequential containers (vector, deque, list), associative containers (map, set), container adapters (queue, stac)

STL is a very important template in C/C++ development, and the various containers defined in it are also very convenient for all of us to use. Below, we briefly talk about some commonly used containers. Here we do not involve the basic operations of containers and so on, just to discuss the characteristics of each container. Commonly used containers in STL include: sequential containers (vector, deque, list), associative containers (map, set), container adapters (queue, stac).

1. Sequential container

(1) vector
A vector is a dynamic array with continuous storage space in memory and supports fast random access. Due to the continuous storage space, the efficiency of insertion and deletion operations is relatively slow. Vector has multiple constructors. The default constructor is to construct a memory space with an initial length of 0, and the allocated memory space grows dynamically in multiples of 2, that is, the memory space grows according to 20, 21, 22, 23. ....Increase, in the process of push_back, if it is found that the allocated memory space is insufficient, then reallocate a continuous memory space whose size is twice the current continuous space, and then copy the elements in the original space to the new In the space, the performance consumption is relatively large, especially when the element is non-internal data (non-internal data is often constructed and the copy constructor is quite complicated). Another common problem with vectors is the clear operation. The clear function only clears the size of the vector to zero, but the elements in the vector are not eliminated in the memory, so in the process of using the vector, you will find that the memory consumption will increase and cause memory leaks. The method that is often used now is swap function to solve: 

copy code code show as below:

vector<int> V;
V.push_back(1); 
V.push_back(2);
V.push_back(1); 
V.push_back(2);
vector<int>().swap(V); 
//或者 V.swap(vector<int>());

Use the swap function to swap with the temporary object, so that the memory of the V object is the memory of the temporary object, and the memory of the temporary object is the memory of the V object. After the swap, the temporary object disappears and the memory is freed.

(2) deque
deque is similar to vector and supports fast random access. The biggest difference between the two is that vector can only insert data at the end, while deque supports double-end insertion of data. The memory space distribution of deque is continuous of small pieces. The small pieces are connected by a linked list. In fact, there is a map pointer inside. The reallocation of the deque space is faster than that of the vector. After the space is reallocated, the original elements do not need to be copied.

(3) The list
list is a doubly linked list, so its memory space can be discontinuous, and data is accessed through pointers, which makes the random storage of the list very inefficient, so the list does not provide the [] operator. overloaded. But a list can well support insertion and deletion anywhere, just by moving the corresponding pointer.

(4) In actual use, how to choose which of these three containers should be determined according to your needs. Generally, the following principles should be followed:
1) If you need efficient random access, you don't care about insertion and deletion. Efficiency, use vector
2) If you need a lot of insertions and deletions, and don't care about random access, you should use list
3) If you need random access, and you care about insertion and deletion of data at both ends, you should use deque

2. Associative Containers

(1)map
map是一种关联容器,该容器用唯一的关键字来映射相应的值,即具有key-value功能。map内部自建一棵红黑树(一种自平衡二叉树),这棵树具有数据自动排序的功能,所以在map内部所有的数据都是有序的,以二叉树的形式进行组织。

这是map的模板:
template < class Key, class T, class Compare= less<Key>, class Allocator=allocator< pair<const Key,T> > > class map;

从模板中我们可以看出,再构造map时,是按照一定的顺序进行的。map的插入和删除效率比其他序列的容器高,因为对关联容器来说,不需要做内存的拷贝和移动,只是指针的移动。由于map的每个数据对应红黑树上的一个节点,这个节点在不保存你的数据时,是占用16个字节的,一个父节点指针,左右孩子指针,还有一个枚举值(标示红黑色),所以map的其中的一个缺点就是比较占用内存空间。

(2)set
set也是一种关联性容器,它同map一样,底层使用红黑树实现,插入删除操作时仅仅移动指针即可,不涉及内存的移动和拷贝,所以效率比较高。set中的元素都是唯一的,而且默认情况下会对元素进行升序排列。所以在set中,不能直接改变元素值,因为那样会打乱原本正确的顺序,要改变元素值必须先删除旧元素,再插入新元素。不提供直接存取元素的任何操作函数,只能通过迭代器进行间接存取。

set模板原型:
template <class Key, class Compare=class<Key>, class Alloc=STL_DEFAULT_ALLOCATOR(Key) > class set;

set支持集合的交(set_intersection)、差(set_difference)、并(set_union)及对称差(set_symmetric_difference) 等一些集合上的操作。

3、容器适配器

(1)queue
queue是一个队列,实现先进先出功能,queue不是标准的STL容器,却以标准的STL容器为基础。queue是在deque的基础上封装的。之所以选择deque而不选择vector是因为deque在删除元素的时候释放空间,同时在重新申请空间的时候无需拷贝所有元素。

其模板为:
template < TYPENAME _Sequence="deque<_TP" typeneam _Tp,> > class queue;

(2)stack
stack是实现先进后出的功能,和queue一样,也是内部封装了deque,这也是为啥称为容器适配器的原因吧(纯属猜测)。自己不直接维护被控序列的模板类,而是它存储的容器对象来为它实现所有的功能。stack的源代码原理和实现方式均跟queue相同。

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324896365&siteId=291194637