C++高性能并行编程与优化 - 课件 - 17 由浅入深学习 map 容器由浅入深学习 map 容器 by 彭于斌( @archibate ) 我负责监督你鞋习 ! 我负责监督你鞋习 ! 本期看点: 用方括号 [ ] 取出 map 元素居然是错误的! 能不能在遍历的同时删除元素?安全吗? emplace , emplace_hint , try_emplace 的区别? 课程安排 1. vector 容器初体验 & 迭代器入门 (BV1qF411T7sd) 2 2. 你所不知道的 set 容器 & 迭代器分类 (BV1m34y157wb) 3. string , string_view , const char * 的爱恨纠葛 (BV1ja411M7Di) 4. 万能的 map 容器全家桶及其妙用举例 ( 本期 ) 5. 函子 functor 与 lambda 表达式知多少 6. 通过实战案例来学习 STL 算法库 7. C++ 标准输入输出流 & 字符串格式化 第一章:读取与写入 我负责监督你鞋习 ! 我负责监督你鞋习 ! map 查找元素的两个接口 • map 提供了两个查找元素的接口,一曰 [] ,二曰 at 。 • 那么他们两个又有什么区别呢?很多新手都分不清他俩,可能只认识 [] 。 读取 map 元素 • mapm; • 读取 map 中指定键值的元素有两种方法。 • val = m[“key”]; 0 码力 | 90 页 | 8.76 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 13 C++ STL 容器全解之 vectorC++ STL 容器全解之 vector by 彭于斌( @archibate ) 往期录播: https://www.bilibili.com/video/BV1fa411r7zp 课程 PPT 和代码: https://github.com/parallel101/course C++ 标准库五大件:容器( container ) C++ 标准库五大件:迭代器( iterator 侯捷 STL 侯捷 STL vector 容器 vector 容器:构造函数 • vector 的功能是长度可变的数组,他里面的数据 存储在堆上。 • vector 是一个模板类,第一个模板参数是数组里 元素的类型。 • 例如,声明一个元素是 int 类型的动态数组 a : • vectora; vector 容器:构造函数和 size • vector 可以在构造时指定初始长度。 vector a(4); • 之后可以通过 a.size() 获得数组的长度。 • 比如右边这段代码会得到 4 。 • size_t size() const noexcept; vector 容器: operator[] • 要访问 vector 里的元素,只需用 [] 运算符 : • 例如 a[0] 访问第 0 个元素(人类的第一 个) • 例如 a[1] 访问第 1 个元素(人类的第二 0 码力 | 90 页 | 4.93 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 14 C++ 标准库系列课 - 你所不知道的 set 容器com/video/BV1qF411T7sd 课程安排 1. vector 容器初体验 & 迭代器入门 (BV1qF411T7sd) 2. 你所不知道的 set 容器 & 迭代器分类 ( 本期 ) 3. string , string_view , const char * 的爱恨纠葛 4. 万能的 map 容器全家桶及其妙用举例 5. 函子 functor 与 lambda 表达式知多少 6 标准输入输出流 & 字符串格式化 8. traits 技术,用户自定义迭代器与算法 9. allocator ,内存管理与对象生命周期 set 和 vector 的区别 • 都是能存储一连串数据的容器 。 • 区别 1 : set 会自动给其中的 元素从小到大排序,而 vector 会保持插入时的顺序。 • 区别 2 : set 会把重复的元素 去除,只保留一个,即去重。 • 区别 3 这样只会按字符串指针的地址去判断相等, 而不是所指向字符串的内容。 set 的排序:自定义排序函数 • set 作为模板类,其实有两 个模板参数: set• 第一个 T 是容器内元素的类 型,例如 int 或 string 等。 • 第二个 CompT 定义了你想 要的比较函子, set 内部会 调用这个函数来决定怎么排 序。 • 如果 CompT 不指定,默认 0 码力 | 83 页 | 10.23 MB | 1 年前3
现代C++ 教程:高速上手C++11/14/17/20. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 3 目录 目录 第 4 章容器 46 4.1 线性容器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 std::forward_list . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.2 无序容器 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 4.3 其次,C++11 还提供了统一的语法来初始化任意的对象,例如: Foo foo2 {3, 4}; 结构化绑定 结构化绑定提供了类似其他语言中提供的多返回值的功能。在容器一章中,我们会学到 C++11 新 增了 std::tuple 容器用于构造一个元组,进而囊括多个返回值。但缺陷是,C++11/14 并没有提供一种 简单的方法直接从元组中拿到并定义元组中的元素,尽管我们可以使用 std::tie0 码力 | 83 页 | 2.42 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 04 从汇编角度看编译器优化课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: 编译器优化:举个例子 编译器优化:我毕竟不是万能的 结论:尽量避免代码复杂化,避免使用会造 成 new/delete 的容器。 简单的代码,比什么优化手段都强。 造成 new/delete 的容器:我是说,内存分配在堆上的容器 • 存储在堆上(妨碍优化): • vector, map, set, string, function, any • unique_ptr, shared_ptr, weak_ptr :强迫编译器在编译期求值 结论:如果发现编译器放弃了自动优化,可以 用 constexpr 函数迫使编译器进行常量折叠! 不过, constexpr 函数中无法使用非 constexpr 的容器: vector, map, set, string 等 …… constexpr :强迫编译器在编译期求值(续) 发现:会让编译变得很慢,因为这 50000 次迭代是在编译期进行的。 第 2 章:内联0 码力 | 108 页 | 9.47 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: 数量超过了 CPU 核心数量,通常就无法再加速了,这就是为什么要买更多核的电脑。 • 也有一种说法,认为要用 c 趋向于无穷时的时间复杂度来衡量,比如 O(n/c) 应该变成 O(1) 。 映射( map ) 1 个线程,独自处理 8 个元素的映射,花了 8 秒 用电量: 1*8=8 度电 结论:串行映射的时间复杂度为 O(n) ,工作复杂度为 O(n) ,其中 n 是元素个数 并行映射 4 个线程,每人处理 可见,并行后虽然降低了时间复杂度,但是以提升工作复杂度为代价! 更多细节,敬请期待 GPU 专题,我们会以 CUDA 为例详细探讨两全方案。 封装好了: parallel_scan 第 3 章:性能测试 案例: map 与 reduce 的组合 测试所花费时间: tbb::tick_count::now() 并行和串行的速度比较 如何评价 • 公式:加速比 = 串行用时 ÷ 并行用时 • 理想加速比应该是核心的数量。0 码力 | 116 页 | 15.85 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 15 C++ 系列课:字符与字符串b 课程安排 1. vector 容器初体验 & 迭代器入门 (BV1qF411T7sd) 2. 你所不知道的 set 容器 & 迭代器分类 (BV1m34y157wb) 3. string , string_view , const char * 的爱恨纠葛 ( 本期 ) 4. 万能的 map 容器全家桶及其妙用举例 5. 函子 functor std::format 4. 第三方库提供的 fmt::format ( https://github.com/fmtlib/fmt ) 5. 参考小彭老师在 zeno 里手撸的两个函数(能支持任意 STL 容器的打印) : • https://github.com/zenustech/zeno/blob/master/zeno/include/zeno/utils/to_string.h • https://github 强引用胖指针: string • 刚刚说的 string 容器,是掌握着字符串生命周期( lifespan )的胖指针。 • 这种掌管了所指向对象生命周期的指针称为强引用( strong reference )。 • 这个强引用的强,体现在哪里? • 当 string 容器被拷贝时,其指向的字符串也会被拷贝(深拷贝)。 • 当 string 容器被销毁时,其指向的字符串也会被销毁(内存释放)。 s10 码力 | 162 页 | 40.20 MB | 1 年前3
Hello 算法 1.1.0 C++ 版{ nodes.push_back(ListNode(i)); } // 长度为 n 的哈希表占用 O(n) 空间 unordered_mapmap; for (int i = 0; i < n; i++) { map[i] = to_string(i); } } 如图 2‑17 所示,此函数的递归深度为 ? ,即同时存在 ? 个未返回的 linear_recur() File: hash_map.cpp === /* 初始化哈希表 */ unordered_map map; /* 添加操作 */ // 在哈希表中添加键值对 (key, value) map[12836] = " 小哈"; map[15937] = " 小啰"; map[16750] = " 小算"; map[13276] = " 小法"; map[10583] name = map[15937]; /* 删除操作 */ // 在哈希表中删除键值对 (key, value) map.erase(10583); 哈希表有三种常用的遍历方式:遍历键值对、遍历键和遍历值。示例代码如下: // === File: hash_map.cpp === /* 遍历哈希表 */ // 遍历键值对 key->value for (auto kv: map) { cout 0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0b5 C++版{ nodes.push_back(ListNode(i)); } // 长度为 n 的哈希表占用 O(n) 空间 unordered_mapmap; for (int i = 0; i < n; i++) { map[i] = to_string(i); } } 如图 2‑17 所示,此函数的递归深度为 ? ,即同时存在 ? 个未返回的 linear_recur() File: hash_map.cpp === /* 初始化哈希表 */ unordered_map map; /* 添加操作 */ // 在哈希表中添加键值对 (key, value) map[12836] = " 小哈"; map[15937] = " 小啰"; map[16750] = " 小算"; map[13276] = " 小法"; map[10583] string name = map[15937]; /* 删除操作 */ // 在哈希表中删除键值对 (key, value) map.erase(10583); 哈希表有三种常用遍历方式:遍历键值对、遍历键和遍历值。 // === File: hash_map.cpp === /* 遍历哈希表 */ // 遍历键值对 key->value for (auto kv: map) { cout 0 码力 | 377 页 | 30.69 MB | 1 年前3
Hello 算法 1.0.0 C++版{ nodes.push_back(ListNode(i)); } // 长度为 n 的哈希表占用 O(n) 空间 unordered_mapmap; for (int i = 0; i < n; i++) { map[i] = to_string(i); } } 如图 2‑17 所示,此函数的递归深度为 ? ,即同时存在 ? 个未返回的 linear_recur() File: hash_map.cpp === /* 初始化哈希表 */ unordered_map map; /* 添加操作 */ // 在哈希表中添加键值对 (key, value) map[12836] = " 小哈"; map[15937] = " 小啰"; map[16750] = " 小算"; map[13276] = " 小法"; map[10583] name = map[15937]; /* 删除操作 */ // 在哈希表中删除键值对 (key, value) map.erase(10583); 哈希表有三种常用的遍历方式:遍历键值对、遍历键和遍历值。示例代码如下: // === File: hash_map.cpp === /* 遍历哈希表 */ // 遍历键值对 key->value for (auto kv: map) { cout 0 码力 | 378 页 | 17.59 MB | 1 年前3
共 192 条
- 1
- 2
- 3
- 4
- 5
- 6
- 20













