目录
1 概述
映射是关联容器,存储由键值和映射值的组合组成的元素,遵循特定的顺序。
在映射中,键值通常用于对元素进行排序和唯一标识,而映射的值存储与该键关联的内容。键和映射值的类型可能不同,并在成员类型value_type中分组在一起,该类型是将两者组合在一起的对类型:
typedef pair<const Key,T> value_type;
在内部,映射中的元素总是按照其键进行排序,遵循由其内部比较对象(类型为Compare)指示的特定严格弱排序标准。
map容器通过关键字访问单个元素的速度通常unordered_map容器慢,但它们允许根据子集的顺序直接迭代。
映射中的映射值可以通过使用括号运算符(operator[])的相应键直接访问。
映射通常被实现为二叉搜索树
其类图如下:
2 使用实例
void MapSuite::find()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
auto it = a.find('e');
TEST_ASSERT_EQUALS('e', it->first)
TEST_ASSERT_EQUALS(50, it->second)
it = a.find('h');
TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::count()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
TEST_ASSERT_EQUALS(1, a.count('e'))
TEST_ASSERT_EQUALS(0, a.count('h'))
}
3 接口使用
3.1 construct
namespace helper_of_map {
bool function_compare(char l, char r) { return l < r; }
struct object_compare
{
bool operator()(const char& l, const char& r) { return l < r; }
};
}
void MapSuite::construct()
{
std::map<char, int> a;
std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50}};
std::map<char, int> c(b.begin(), b.end());
std::map<char, int> d(b);
std::map<char, int> e({ { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } , { 'a', 10 } });
std::map<char, int, helper_of_map::object_compare> f;
std::map<char, int, bool(*)(char, char)> g(helper_of_map::function_compare);
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(5, c.size())
TEST_ASSERT_EQUALS(5, d.size())
TEST_ASSERT_EQUALS(5, e.size())
TEST_ASSERT_EQUALS(true, f.empty())
TEST_ASSERT_EQUALS(true, g.empty())
}
说明:
- 构造时可以指定函数对象作为比较函数
- 构造时可以指定函数指针作为比较函数
3.2 assigns
void MapSuite::assigns()
{
std::map<char, int> a = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }, { 'e', 60 } };
std::map<char, int> b;
std::map<char, int> c;
std::map<char, int> d;
b = a;
c = { { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }, { 'a', 10 } };
d = std::map<char, int>({ { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } });
TEST_ASSERT_EQUALS(5, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(5, c.size())
TEST_ASSERT_EQUALS(5, d.size())
}
3.3 iterators
void MapSuite::iterators()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 }};
char keys[] = { 'a', 'b' , 'c', 'd', 'e' };
char rkeys[] = { 'e', 'd' , 'c', 'b', 'a' };
int values[] = { 10, 20, 30, 40, 50 };
int rvalues[] = { 50, 40, 30, 20, 10 };
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
{
TEST_ASSERT_EQUALS(keys[index], it->first)
TEST_ASSERT_EQUALS(values[index++], it->second)
}
index = 0;
for(auto it = a.cbegin(); it != a.cend(); ++it)
{
TEST_ASSERT_EQUALS(keys[index], it->first)
TEST_ASSERT_EQUALS(values[index++], it->second)
}
index = 0;
for(auto it = a.rbegin(); it != a.rend(); ++it)
{
TEST_ASSERT_EQUALS(rkeys[index], it->first)
TEST_ASSERT_EQUALS(rvalues[index++], it->second)
}
index = 0;
for(auto it = a.crbegin(); it != a.crend(); ++it)
{
TEST_ASSERT_EQUALS(rkeys[index], it->first)
TEST_ASSERT_EQUALS(rvalues[index++], it->second)
}
}
3.4 capacity
void MapSuite::capacity()
{
std::map<char, int> a;
std::map<char, int> b = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(0, a.size())
TEST_ASSERT_EQUALS(5, b.size())
TEST_ASSERT_EQUALS(b.max_size(), a.max_size())
}
3.5 access
void MapSuite::access()
{
std::map<char, int> a;
std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }};
bool hasExcpetion = false;
a['a'] = 10;
a['b'] = 20;
b.at('a') = 20;
b.at('b') = 30;
try
{
b.at('c') = 40;
}
catch(...)
{
hasExcpetion = true;
}
TEST_ASSERT_EQUALS(10, a['a'])
TEST_ASSERT_EQUALS(20, a['b'])
TEST_ASSERT_EQUALS(20, b['a'])
TEST_ASSERT_EQUALS(30, b['b'])
TEST_ASSERT_EQUALS(true, hasExcpetion)
}
说明:
- []函数如果map中没有对应key则添加,value是对应类型的默认值
- at函数如果map中没有对应key则抛异常
3.6 insert
void MapSuite::insert()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
std::map<char, int> b;
std::map<char, int> c;
std::map<char, int>::iterator it;
std::pair<std::map<char, int>::iterator,bool> r = a.insert({ 'b', 20 });//{ 'b', 20 } no inserted
if(r.second == false)
{
it = r.first;
TEST_ASSERT_EQUALS('b', it->first)//*it = { 'b', 20 }
}
a.insert(it, {'f', 60 });
it = a.insert(it, {'g', 70 });
TEST_ASSERT_EQUALS('g', it->first)
it = a.insert(it, {'f', 60 }); //no inserted
TEST_ASSERT_EQUALS('f', it->first)
b.insert(a.begin(), a.end());
c.insert({ {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } });
int array[] = { 10, 20, 30, 40, 50, 60, 70 };
int index = 0;
for(auto it = a.begin(); it != a.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], it->second)
index = 0;
for(auto it = b.begin(); it != b.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], it->second)
index = 0;
for(auto it = c.begin(); it != c.end(); ++it)
TEST_ASSERT_EQUALS(array[index++], it->second)
}
说明:
- 不带位置参数插入函数,返回std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素
- 带位置参数插入函数,返回iterator,指向新加入元素或集合中已存在元素。
3.7 erase
void MapSuite::erase()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
auto it = a.erase(a.begin()); // { 'b', 20 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 }
TEST_ASSERT_EQUALS('b', it->first)
TEST_ASSERT_EQUALS(1, a.erase('c'))// { 'b', 20 }, { 'd', 40 }, {'e', 50 }
TEST_ASSERT_EQUALS(0, a.erase('c'))
it = a.begin();
++it;
TEST_ASSERT_EQUALS('d', it->first)
it = a.erase(it, a.end()); // { 'b', 20 }
TEST_ASSERT_EQUALS(1, a.size())
}
说明:
- 按值删除返回删除元素个数
- 按位置删除返回iterator指向被删除元素的下一位置
3.8 swap
void MapSuite::swap()
{
std::map<char, int> a;
std::map<char, int> b = { { 'a', 10 }, { 'b', 20 }};
TEST_ASSERT_EQUALS(true, a.empty())
TEST_ASSERT_EQUALS(2, b.size())
a.swap(b);
TEST_ASSERT_EQUALS(2, a.size())
TEST_ASSERT_EQUALS(true, b.empty())
}
3.9 clear
void MapSuite::clear()
{
std::map<char, int> a = { { 'a', 10 }, { 'b', 20 }};
TEST_ASSERT_EQUALS(2, a.size())
a.clear();
TEST_ASSERT_EQUALS(true, a.empty())
}
3.10 emplace
void MapSuite::emplace()
{
std::map<char, int> a;
a.emplace('a', 10);
a.emplace('b', 20);
TEST_ASSERT_EQUALS(2, a.size())
auto r = a.emplace('a', 10);
TEST_ASSERT_EQUALS('a', r.first->first)
TEST_ASSERT_EQUALS(false, r.second)
TEST_ASSERT_EQUALS(2, a.size())
}
- 返回值为std::pair对象,pair::first指新加入元素或集合中已存在元素,pair::second为true说明插入成功,为false说明集合中已有该元素
3.11 emplace_hint
void MapSuite::emplace_hint()
{
std::map<char, int> a = { { 'a', 10 }, { 'b', 20 } };
auto it = a.emplace_hint(a.begin(), 'c', 30);
TEST_ASSERT_EQUALS('c', it->first);
it = a.emplace_hint(it, 'b', 20);
TEST_ASSERT_EQUALS('b', it->first)
}
说明:
- 返回值为iterator对象,指向新加入元素或集合中已存在元素。
3.12 key_comp
void MapSuite::key_comp()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
std::map<char, int> b;
std::map<char, int>::key_compare compare = a.key_comp();
char hightest = a.rbegin()->first;
for(auto it = a.begin(); it != a.end(); ++it)
{
if(compare(it->first, hightest))
b.insert(*it);
}
int index = 0;
char array [] = { 'a', 'b', 'c', 'd', 'e' };
for(auto i : b)
{
TEST_ASSERT_EQUALS(array[index++], i.first)
}
TEST_ASSERT_EQUALS(4, b.size())
}
说明:
- 对map来说,key_comp的参数类型是key的类型这里是char
3.13 value_comp
void MapSuite::value_comp()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
std::map<char, int> b;
std::map<char, int>::value_compare compare = a.value_comp();
auto hightest = *a.rbegin();
for(auto it = a.begin(); it != a.end(); ++it)
{
if(compare(*it, hightest))
b.insert(*it);
}
int index = 0;
int array [] = { 10, 20, 30, 40, 50 };
for(auto i : b)
{
TEST_ASSERT_EQUALS(array[index++], i.second)
}
TEST_ASSERT_EQUALS(4, b.size())
}
- 对map来说,value_comp的参数是类型是std::pair<char, int>而不是int
3.14 find/count
void MapSuite::find()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
auto it = a.find('e');
TEST_ASSERT_EQUALS('e', it->first)
TEST_ASSERT_EQUALS(50, it->second)
it = a.find('h');
TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::count()
{
std::map<char, int> a = { {'e', 50 }, { 'a', 10 }, { 'b', 20 }, { 'c', 30 }, { 'd', 40 } };
TEST_ASSERT_EQUALS(1, a.count('e'))
TEST_ASSERT_EQUALS(0, a.count('h'))
}
3.15 upper_bound/upper_bound/equal_range
void MapSuite::lower_bound()
{
std::map<char, int> a = { { 'a', 10 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
auto it = a.lower_bound('b');//>=b
TEST_ASSERT_EQUALS('c', it->first)
it = a.lower_bound('d');//>=d
TEST_ASSERT_EQUALS('d', it->first)
it = a.lower_bound('f');
TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::upper_bound()
{
std::map<char, int> a = { { 'a', 10 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
auto it = a.upper_bound('c'); // > c
TEST_ASSERT_EQUALS('d', it->first)
it = a.upper_bound('f');// > f
TEST_ASSERT_EQUALS(true, it == a.end())
}
void MapSuite::equal_range()
{
std::map<char, int> a = { { 'a', 10 }, { 'c', 30 }, { 'd', 40 }, {'e', 50 } };
auto it = a.equal_range('c'); // >=c & > c
TEST_ASSERT_EQUALS('c', it.first->first)
TEST_ASSERT_EQUALS('d', it.second->first)
it = a.equal_range('b'); // >= b & > b
TEST_ASSERT_EQUALS('c', it.first->first)
TEST_ASSERT_EQUALS('c', it.second->first)
}
说明:
- lower_bound 返回第一个大于等(>=)于指定值的iterator
- upper_bound 返回第一个大于(>)指定值的iterator
- equal_range 返回std::pair对象, pair::first是第一个大于等(>=)于指定值的iterator,pair::second是第一个大于(>)指定值的iterator
3.16 get_allocator
void MapSuite::get_allocator()
{
std::map<char,int> a;
auto allocator = a.get_allocator();
std::pair<const char,int>* p = allocator.allocate(5);
allocator.deallocate(p, 5);
try
{
p = allocator.allocate(allocator.max_size() + 1);
}
catch(...)
{
p = nullptr;
}
TEST_ASSERT_EQUALS(true, p == nullptr)
}