概述
关联容器都不支持顺序容器的位置相关的操作,例如push_front或push_back。而且,关联容器也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作。
map
类似顺序容器,关联容器也是模板。为了定义一个map,我们必须指定关键字和值的类型。当从map中提取一个元素时,会得到一个pair类型的对象。简单来说,pair是一个模板类型,保存两个名为first和second的数据成员,map所使用的的pair用first成员保存关键字,second成员保存对应的值。关联容器的迭代器都是双向的。
定义关联容器
可以构造空容器,也可以拷贝构造,在新标准下可以对关联容器进行值初始化。例如:
set<string>exclude={"the","but"};
map<string, string>authors = { {"joyce","james"},{"Austen","jane"} };
multimap和multiset
map或者set中的关键字必须是唯一的,但是容器multimap和multiset就没有限制,他们都允许多个元素具有相同的关键字。例如:
vector<int>v1;
for (vector<int>::size_type i = 0; i < 10; ++i)
{
v1.push_back(i);
v1.push_back(i);
}
cout << v1.size();
set<int>s1(v1.begin(), v1.end());
multiset<int>m2(v1.begin(), v1.end());
cout << s1.size() <<" "<< m2.size();
会输出20 10 20;
使用关键字类型的比较函数
用尖括号指出要定义哪种类型的容器,自定义操作类型必须在尖括号中紧跟着元素类型给出。
例如:
class number
{
int a;
int b;
};
int main()
{
multiset<number>s1;
number one;
s1.insert(one);
}
这样就会报错。
比较操作类型是函数指针类型;例如
class number
{
public:
int a = 1;
int b = 2;
};
bool compare(const number& one, const number& two)
{
return one.a >= two.b;
}
int main()
{
multiset<number,decltype(compare)*>s1(compare);
number one;
one.a = 3;
one.b = 4;
s1.insert(one);
number two;
s1.insert(two);
for (auto num : s1)
{
cout << num.a << " " << num.b;
break;
}
}
这表示从compare来初始化s1对象,通过调用compare来为这些元素排序。
pair类型
pair在头文件utility中,pair是一个用来生成特定类型的模板,下面是创建pair:
pair<string,string>anon;
pair<string,size_t>word_count;
pari的默认构造函数对数据成员进行初始化。因此anon是一个包含两个空string的pair,我们也可以对每个成员提供初始化器:
pair<string,stirng>
与其他标准库类型不同,pair的数据成员是public的,两个成员分别命名为first和second.
pair上的操作
pair<T1,T2>p;
pair<T1,T2>p(v1,v2)///p是一个pair,first和second成员分别用v1和v2进行初始化。
make_pair<v1,v2) ///返回一个用v1和v2初始化的pair。pair的类型从v1和v2推断出来。
创建pair对象的函数
例如:
pair<string, int>process(vector<string>& v)
{
if (!v.empty())
{
return { v.back(),v.back().size() }; ///列表初始化
}
else
{
return pair<string, int>();
}
}
我们还可以使用make_pair来生成pair对象,例如:
return make_pair(v.back(),v.back().size());
初始化列表
例如:
vector<string>process()
{
string expected;
string actual;
if (expected.empty())
{
return {};
}
else if (expected == actual)
{
return { "functionx","okey" };
}
else
{
return { "functionX",expected,actual };
}
}
关联容器操作
关联容器额外的类型别名:
key_type 此容器类型的关键字类型
mapped_type 每个关键字关联的类型;只适用于map
value_type 对于set,与key_type相同
对于map,为pair<const key_type,mapped_type>
由于我们不能改变一个元素的关键字,因此这些pair的关键字部分是const的:
set<string>::value_type v1; string
set<string>key_type v2; string
map<string,int>::value_type v3; pair<const string,int>
map<string,int>::key_type v4; string
map<string,int>::mapped_type v5; int
和顺序容器一样,我们使用作用域运算符来提取一个类型的成员—例如,map<string,int>::key_type;
关联容器迭代器
必须记住,一个map的value_type是一个pair,我们可以改变pair的值,但不能改变关键字的值。
set的迭代器是const,可以用一个set迭代器来读取元素的值,但不能修改。
遍历关联容器
和顺序容器一样。
添加元素
insert有两个版本,分别接受一对迭代器,或是一个初始化器列表。
vector<int>v1 = { 2,3,4,5,2,3,6 };
set<int>set2;
set2.insert(v1.cbegin(), v1.cend());
set2.insert({ 2,34,23,4,23,4 });
向map添加元素
word_count.insert({word,1}};
word_count.insert(make_pair(word,1));
word_count.insert(pair<string,size_t>(word,1));
word_count.insert(map<string,size_t>::value_type(word,1));