标准模板库 STL 简单总结


常用容器vector, list, map, set


(1.1)vector的头文件
#include <vector>
using std::vector;
vector<int> v_ints;
std::vector<int> v_ints;

(1.2)vector的构造
vector<int> first;                                // empty vector of ints
vector<int> second (4,100);                       // four ints with value 100
vector<int> third (second.begin(),second.end());  // iterating through second
vector<int> fourth (third);                       // a copy of third


(1.3)vector成员函数:
c.at(idx) , 类似操作符[], 返回索引idx所指的数据的引用,如果idx越界,抛出out_of_range。
c.begin() 返回指向首部数据的迭代器。返回类型为 vector<T>::iterator。
c.end() 返回指向尾部数据的迭代器,此迭代器不执行任何内容。
c.empty() 判断容器是否为空,返回类型bool。
c.capacity() 返回容器中数据个数,返回类型为size_type。
c.max_size() 返回容器中最大数据的数量,返回类型为size_type。
c.size() 返回容器中实际元素的个数,返回类型为size_type。

STL容器的capacity属性,表示STL在发生realloc前能允许的最大元素数,也可以理解为预分配的内存空间。例如一个vector<int> v的capacity为5,当插入第6个元素时,vector会realloc,vector内部数据会复制到另外一个内存区域。这样之前指向vector中的元素的指针、迭代器等等均会失效。
max_size属性和capacity不同,表示STL容器允许的最大元素数,通常,这个数是一个很大的常整数,可以理解为无穷大。这个数目与平台和实现相关,在我的机器上vector<int>的max_size为1073741823,而string的max_size为4294967294。因为max_size很大~所以基本不会发生元素数超过max_size的情况,只需知道两者区别即可。
并不是所有的容器都会发生realloc,List,Map/Multimap,Set/Multiset的元素在内存中散布,不预分配内存,所以不会产生realloc的情况,对于这些容器,其capacity是无意义的,所以这些容器没有capacity()成员函数,也没有capacity属性。

void resize(size_type sz, T c=T()), 重新分配大小;
    myvector.resize(5);
    myvector.resize(8,100); // eight of value = 100

c.front() 返回第一个数据的引用。比如vector<string>::front()返回的就是string的引用。
c.push_back(T) 在尾部加入一个数据,参数为模板类型,是最常用的vector增长方式
c.pop_back() 删除最后一个数据。原型void pop_back();
c.clear() 移除容器中所有数据。
c.erase(pos) 删除pos位置的数据,返回下一个数据的iterator。
c.erase(beg,end) 删除[beg,end)区间的数据,返回下一个数据的iterator。


list作为非连续的存储, 不提供[]操作符和at(index)等随机访问函数. 而Vector是类似数组的连续存储空间, 具有比较强的随机访问能力, 所以Vector提供[]操作符.
但Vector不具有insert. 

(2.1)list的构造
list<int> first;                                // empty list of ints
list<int> second (4,100);                       // four ints with value 100
list<int> third (second.begin(),second.end());  // iterating through second
list<int> fourth (third);                       // a copy of third

int myints[] = {16,2,77,29};
list<int> fifth (myints, myints + sizeof(myints) / sizeof(int) );


for (list<int>::iterator it = fifth.begin(); it != fifth.end(); it++)  
  cout << *it << endl;
(2.2)list成员函数:

Iterators:
  list::begin(), 返回list::iterator
  list::end(), 返回list::iterator, 注意遍历的边界是 != list::end();

Capacity:
  bool list::empty() const;
  size_type size() const;  return the number of elements in list
  size_type max_size() const;
  

Modifiers:
void pop_front():  Removes the first element in the list container, effectively reducing the list size by one.This calls the removed element's destructor.
void push_front(const T &x): Insert an element at begin,
void pop_back(): Remove the last element in the rear of list, and calls the removed element's destructor.
void push_back(const T &x):



Insert elements
iterator insert ( iterator position, const T& x );
void insert ( iterator position, size_type n, const T& x );


Erase elements
iterator erase ( iterator position );
iterator erase ( iterator first, iterator last );
Removes from the list container either a single element (position) or a range of elements ([first,last]). calling each element's destructor before.
注意earse的返回值, 返回(删除后)剩余接点元素的iterator, 不能用iterator++的方式遍历删除, 正确的删除操作如下:
list<int> testlist;
// 增加:
for(int i=0; i<10; i++) testlist.push_back(i);
// 删除:
list<int>::iterator it;
for(it = testlist.begin(); it != testlist.end() )
    testlist.earse(it);
// 如果list中的元素是类, 那么要手动调用析构函数. 



Remove elements with specific value
void remove ( const T& value );
Removes from the list all the elements with a specific valueThis calls the destructor of these objects and reduces the list size by the amount of elements removed.
remove(T &x) 成员函数是删除特定值的操作, 比如students.remove"Jim";


Clear content
void clear ( );
All the elements in the list container are dropped: their destructors are called, and then they are removed from thelist container, leaving it with a size of 0.


Sort elements in container
  void sort ( );
Sorts the elements in the container from lower to higher. The sorting is performed by comparing the elements in the container in pairs using a sorting algorithm.


Reverse the order of elements
void reverse ( );
Reverses the order of the elements in the list container. All iterators and references to elements remain valid.


Get allocator
allocator_type get_allocator() const;
Returns the allocator object used to construct the container.



(3.2)map简介:
Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性,它完成有可能在我们处理一对一数据的时候,在编程上提供快速通道。这里说下map内部数据的组织,map内部自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在map内部所有的数据都是有序的
  1. 自动建立Key - value的对应。key 和 value可以是任意你需要的类型。
  2. 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最多查找10次,1,000,000个记录,最多查找20次。
  3. 快速插入Key - Value 记录
  4. 快速删除记录
  5. 根据Key 修改value记录。
  6. 遍历所有记录。

(3.2)map的构造:

std::map<int,string> name; // int 为索引
std::map<char, int> first; // char 为索引
first['a'] = 1;
first['b'] = 2;
map<char,int> second(first.begin(), first.end());
map<char,int> third(second); 

由上面的代码可知map 可以通过[]操作符获取元素, 类似vector的[]. 另外map::iterator也支持解地址(*) 和 指针调用符(->). 
map<Key,T>::iterator it;
(*it).first;             // the key value (of type Key)
(*it).second;            // the mapped value (of type T)
(*it);                   // the "element value" (of type pair<const Key,T>)
it->first;               // same as (*it).first   (the key value)
it->second;              // same as (*it).second  (the mapped value)
map的两个成员map::first和map::second分别代表关键字和数据.


(3.3)map成员函数:

1、向map插入元素

第一种插入方式:
用insert插入pair元素 map1.insert(pair<int,string>(99,"Jim"));

第二种插入方式:
用insert插入type_value元素 map2.insert(map<int,string>::value_type(99,"Jim"));

第三种插入方式:
直接利用[]操作符 map3[99] = "Jim";

类似于"类构造函数的初始化语法", map3[99] = "Jim"的赋值也有效率问题, 
插入99时,先在Map中查找主键为99的项,未找到,然后将一个新的对象插入Map,键是99,值是一个空字符串,插入完成后,将字符串赋为"Jim"; 
该方法会将每个值都赋为缺省值,然后再赋为显示的值,如果元素是类对象,则开销比较大。用第二种插入type_value的方式更加具有效率.
实际上, map::value_type的类型就是pair<const KEY, T &t>.

map::insert()和 map::operator[]的另一个区别是, 如果key已经存在, insert()是无法成功插入元素的, 但是数组操作符[] 就可以覆盖已存在的数据.

question: 实现map::operator=, 以及operator[]


2、查找并获取map中的元素
下标操作符给出了获得一个值的最简单方法:
CString tmp = enumMap[2];
但是,只有当map中有这个键的实例时才对,否则会自动插入一个实例,值为初始化值。
可以使用Find()Count()方法来发现一个键是否存在。

int index = 99;
map<int,string>::iterator it = map1.find(index);
if(it != map1.end()) 
    cout << it->second << endl;
else
    cout << "find nothing" << endl;


3、删除map中的元素
  void erase ( iterator position );
  size_type erase ( const key_type& x );
  void erase ( iterator first, iterator last ); 
Removes from the map container either a single element or a range of elements ([first,last)).
This effectively reduces the container size by the number of elements removed, calling each element's destructor.
  1. iterator erase(iterator it); // 通过一个条目对象删除
  2. iterator erase(iterator first, iterator last); // 删除一个范围
  3. size_type erase(const Key& key); // 通过关键字删除
clear()就相当于 enumMap.erase(enumMap.begin(), enumMap.end());

STL容器的析构:
STL容器在析构之前, 会先调用存储对象的析构函数:

{
  widget w; // 构造函数
  vector<widget> vec;
  vec.push_back(w); // 复制构造函数
}
函数退出时会调用两次~widget(), 如果widget的成员中有指针类型, 并且widget没有实现拷贝构造, 那么编译器自动合成的拷贝构造只是进行了"浅拷贝", 只是复制了指针的值, 两个对象的指针实际指向了同一个地方. 

如果STL容易里存储的是指针类型, 一定要在销毁容器前, 手动释放指针指向的内存.

示例1:
std::map<int, char*> m_map;
char *p = new char(1000);
m_map[0] =  p;

std::map<int, char*>::iterator it;
for(it=m_map.begin(); it != m_map.end(); ++it)
    delete (char*)(it->second);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章