C++复习笔记
c++ primer笔记
关联容器
关联容器支持通过键来高效的查找和读取元素。有两种基本的关联容器类型:map和set。
pair类型
表达式 | 功能 |
---|---|
pair<T1, T2> p1; | 创建一个空的pair对象,它的两个元素分别是TI和T2类型的,采用值初始化。 |
pair<T1, T2> p1(v1, v2); | 创建一个pair对象,它的两个元素分别是TI和T2类型的,first成员初始化为v1,second成员初始化为v2。 |
make_pair(v1, v2); | 以v1和v2的值创建一个pair对象,其元素的类型分别是v1和v2的类型。 |
p1 < p2 | 两个pair对象之间的小于运算,其定义遵循字典次序:如果p1.first < p2.first或者!(p2.first < p1.first) && p1.second < p2.second,则返回true。 |
p1 == p2 | 如果两个pair对象的两个成员分别相等,则两个对象相等,返回true。 |
p.first | 返回p中的first的数据成员 |
p.second | 返回p中的second的数据成员 |
关联类型
关联容器不支持顺序容器中front、push_front、pop_front、back、push_back和pop_back操作。
顺序容器和关联容器相同的操作:
a)三种基础的构造函数
C<T> c;
C<T> c1(c2);
C<T> c(b, e);
b)关系运算
c)begin、end、rbegin和rend操作
d)swap和赋值操作,但是关联容器不支持assgin函数
e)clear和erase操作
f)关于容器大小的操作(size),但是关联容器不支持resize函数。
容器元素是根据键的次序排列。在迭代遍历关联容器时,可确保按键的顺序访问元素,而与元素在容器中的存放位置完全无关。
map类型
map是键-值对的集合。map类型可以理解为关联数组:可以使用键作为下标来获取一个值。关联的本质在于元素的值与某个特定的键相关联,而不同于元素在数组中的位置来获取。
- 项目1map对象的定义
表达式 | 功能 |
---|---|
map<k, v> m; | 创建一个名为m的空map对象,其键值的类型分别为k和v |
map<k, v> m(m2); | 创建m2的副本m,m和m2必须具有相同的键值类型 |
map<k, v> m(b, e); | 创建map类型的对象,存储迭代器b和e标记范围内所有元素的副本。元素的类型必须能转换为pair<const k, v> |
键类型的约束
使用关联容器时,它的键不仅有一个类型,而且还有一个相关的比较函数。默认情况下,标准库使用键类型定义的“<”操作符实现键的比较。
所用的比较函数必须在键类型上严格弱排序的(严格是说在判断的时候会用"<",而不是"<=",弱排序是因为,一旦"<“成立便认为存在”<“关系,返回ture,而忽略了”=“关系和”>"区别,把它们归结为false)。
个人理解,由于map类型的键值是唯一的,所以键类型只有“小于”、“大于”两种关系。如果不满足“小于”关系,则就是“大于”关系。
对于键类型,唯一的约束就是必须支持“<”操作符。对于其他关系操作符没有具体的要求。
- map定义的类型
map对象的元素是键-值对,每个元素包含两个部分,键和与键相关联的值。
表达式 | 解释 |
---|---|
map<K, V>::key_type | 在map容器中,用作索引的键类型 |
map<K, V>::mapped_type | 在map容器中,键相关联的值的类型 |
map<K, v>::value_type | 一个pair类型,first成员是const map<K, V>::key_type类型,second成员是map<K, V>::mapped_type类型。 |
map迭代器进行解引用将产生pair类型的对象
对迭代器进行解引用时,将获得一个引用,指向容器中一个value_type类型的值。对于map类型,其value_type类型是pair类型。
map<string, int>::iterator map_it = word_count.begin();
cout << map_it->first;
cout << " " << map_it->second;
map_it.first = "new"; //error:因为first成员是const类型
++map_it->second;
- 向map中添加元素
有两种方式:一是使用insert成员实现;二是先用下标操作符获取元素,然后给获取的元素赋值。
map:insert的使用
操作 | 含义 |
---|---|
m.insert(e) | e是一个用在m上的value_type类型的值(pair类型)。如果键m.first不在m中,则插入一个值为e.second的新元素;如果m.first在m中已存在,则保持m不变。该函数返回一个pair类型的对象,包含指向键值为e.first元素的map迭代器,以及一个bool类型的对象,表示是否插入成功 |
m.insert(beg, end) | beg和end是标记元素范围的迭代器,其中的元素必须是m.value_type类型的键值对。对于该范围内的所有元素,如果它的键不在m中,则将键值对插入到m中,返回void类型 |
m.insert(iter, e) | e是一个用在m上的value_type类型的值。如果键e.first不在m中,则创建新的元素,并以迭代器iter为起点搜索新元素的存储位置。返回一个迭代器,指向m中具有给定键值的元素 |
- 使用下标访问map对象
map<string, int> word_count;
word_count["Anna"] = 1;
这段程序发生了以下事件:
a)在word_count中查找键值为Anna的元素,没有找到;
b)创建一个新的键值对,这个键值对键类型是const string类型,值为“Anna”。它的值采用值初始化,这里初始化为0;
c)将这个新的键值对插入word_count中;
d)读取新插入的元素,将其值赋值为1.
使用下标访问map与使用下标访问数组或者vector的行为截然不同:使用下标访问不存在的元素将导致在map容器中添加一个新元素,它的键值为下标值(类似于动态查找)。
还有需要注意的是,map迭代器返回value_type类型的值——包括const key_type和mapped_type类型成员的pair对象;而下标操作符返回的是一个mapped_type类型的值。
- 查找和读取map中的元素
虽然通过下标操作符可以访问map中的元素,但是下标操作也有个严重的副作用就是当元素不在map对象中时,会插入一个新的元素。
map提供两种操作count和find,用于检查某个键是否存在且不会插入该键。
操作 | 功能 |
---|---|
m.count(k) | 返回m中k的出现次数 |
m.find(k) | 如果m容器中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端的迭代器 |
- 从map中删除元素
删除操作是通过erase操作实现
操作 | 功能 |
---|---|
m.erase(e) | 删除m中键为k的元素。返回size_type类型的值,表示删除的元素个数(只能是0或1) |
m.erase§ | 从m中删除迭代器p所指向的元素。p必须指向m中确实存在的元素,且不等于m.end()。返回void类型 |
m.erase(b, e) | 从m中删除一段范围内的元素,该范围由迭代器对b和e标记。 |
set类型
set容器只是单纯的键的集合。
set容器支持大部分map的操作:
a) 通用的容器操作;
b) map定义的构造函数;
c) insert操作
d) count和find操作
e) erase操作
但是有两个例外,set容器不支持下标操作,而且没有定义mapped_type类型。在set容器中,value_type不是pair类型,而是和key_type相同的类型。set存储的元素仅仅是键,而没有值,而且和map容器一样,这里的键都是唯一的。