STL容器之map使用和C++11遍历新用法

2019-10-10

STL容器之map使用, unordered_map区别,C++11中auto遍历用法,以及algorithm算法库中for_each的使用方法

C++11 for循环新用法

参考:

C++ 11和C++98相比有哪些新特性

【C++11】新特性——auto的使用

基于范围的 for 循环 (C++11 起)

C++11中引入的auto主要有两种用途:自动类型推断和返回值占位

  • auto在C++98中的标识临时变量的语义,由于使用极少且多余,在C++11中已被删除。
  • 前后两个标准的auto,完全是两个概念。

  • 使用auto
    • 临时变量 auto member : mapStudent
    • 引用 auto &member : mapStudent
    • 可以用类型修饰符const指定只读 const auto &member : mapStudent
  • 使用迭代器

  • 使用for_each

    使用for_each时定义的函数入参遇到的问题,应使用 std::pair<const int, MyClass>&,注意const的位置

    参考:Use of for_each on map elements

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//test_auto.cpp
#include <iostream>
#include <map>
#include<algorithm> //for_each使用
using namespace std;

void funcStudent(std::pair<const int, string> &pair);
int main(int argc, const char *argv[])
{
    std::map<int, string> mapStudent;
    mapStudent[1] = "lilei";
    mapStudent[2] = "zhangsan";
    cout << "======= auto& test case =========" << endl;
    // member此处是引用类型,如果要限定语句块中不允许修改,可以使用类型修饰符const指定: const auto &
    for (auto &member : mapStudent)
    {
        member.second = "x";
    }
    // 打印结果各成员已修改为"x"
    for (auto member : mapStudent)
    {
        cout << member.second << endl;
    }

    cout << "======= auto test case =========" << endl;
    mapStudent.clear();
    mapStudent[1] = "lilei";
    mapStudent[2] = "zhangsan";
    // member此处是临时变量类型,语句块内赋值并不影响mapStudent原始成员值
    for (auto member : mapStudent)
    {
        member.second = "x";
    }
    // 打印结果各成员还是与之前一样
    for (auto member : mapStudent)
    {
        cout << member.second << endl;
    }

    // 演示迭代器用法
    cout << "========= iterator test case =========" << endl;
    for (std::map<int, string>::iterator iter = mapStudent.begin(); iter != mapStudent.end(); iter++)
    {
        cout << iter->second << endl;
    }

    cout << "========= for_each test case =========" << endl;
    // 演示for_each遍历map
    std::for_each(mapStudent.begin(), mapStudent.end(), funcStudent);
    // 打印结果各成员已修改为"123"
    for (auto member : mapStudent)
    {
        cout << member.second << endl;
    }

    return 0;
}

// for_each传入函数,错误,入参并不是迭代器
// 编译报错: /usr/local/include/c++/4.8.5/bits/stl_algo.h:4417:14: 错误:将类型为‘std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char> > >&’的引用初始化为类型为‘std::pair<const int, std::basic_string<char> >’的表达式无效
// void funcStudent(std::map<int, string>::iterator mapStudent)
// {
//     mapStudent->second = "123";
// }

// for_each传入函数,错误,
// 编译报错: /usr/local/include/c++/4.8.5/bits/stl_algo.h:4417:14: 错误:将类型为‘std::pair<int, std::basic_string<char> >&’的引用初始化为类型为‘std::pair<const int, std::basic_string<char> >’的表达式无效__f(*__first);
// void funcStudent(std::pair<int, string> &pair)
// {
//   pair.second = "123";
// }

// for_each传入函数,解引用时, std::map iterator返回std::pair<const key_type, value_type>,
// 而不是 std::pair<key_type, value_type>,所以key需要const修饰
void funcStudent(std::pair<const int, string> &pair)
{
  pair.second = "123";
}

编译执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[xd@localhost ~/workspace/src]$ cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
# gcc 版本 4.8.5 (GCC)
[xd@localhost ~/workspace/src]$ g++ test_auto.cpp -std=c++11
[xd@localhost ~/workspace/src]$ ./a.out
======= auto& test case =========
x
x
======= auto test case =========
lilei
zhangsan
========= iterator test case =========
lilei
zhangsan
========= for_each test case =========
123
123

unordered_map

参考: C++ unordered_map

hash_map ≈ unordered_map

从 C++ 11 开始,hash_map 实现已被添加到标准库中。但为了防止与已开发的代码存在冲突,决定使用替代名称 unordered_map。这个名字其实更具描述性,因为它暗示了该类元素的无序性。

和map比较

新版的hash_map都是unordered_map了,这里只说unordered_map和map.

1
2
3
运行效率方面:unordered_map最高,而map效率较低但 提供了稳定效率和有序的序列。

占用内存方面:map内存占用略低,unordered_map内存占用略高,而且是线性成比例的。

需要无序容器,快速查找删除,不担心略高的内存时用unordered_map;有序容器稳定查找删除效率,内存很在意时候用map。

map的内部实现是二叉平衡树(红黑树);hash_map内部是一个hash_table



Comments