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++ 标准输入输出流 & 字符串格式化 • (*it).first; // K 类型 • (*it).second;// V 类型 map 的遍历:用 C++17 range-based loop • 和 vector 等 STL 容器一样, map 也支持 C++17 的 range-based loop 语法进行遍历 。 • for (auto tmp: m) • 由于刚刚说了, map 真正的“元素类型”是 K-V 对,所以这里的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++高性能并行编程与优化 - 课件 - 03 现代 C++ 进阶:模板元编程课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: 这是一个实现将两个不同类型 vector 逐元素相加的函数。 • 用 decltype(T1{} * T2{}) 算出 T1 和 T2 类型相加以后的结果,并做 为返回的 vector 容器中的数据类型。 恭喜!你已经基本学废了自动类型推导! • 《基本鞋废》 • 怎么样,是不是非常方便呢? • 如果不理解,跳过即可! 函数也是对象:函数式编程 • 你知道吗?函数可以作为另一个函数的参数! • 但是有时候我们希望通过头文件的方式分 离声明和实现,或者想加快编译,这时如 果再用 template class 作为参数就不行了 。 • 为了灵活性,可以用 std::function 容器。 • 只需在后面尖括号里写函数的返回类型和 参数列表即可,比如: • std::function; 如何避免用模板参数 2 :无捕获的 lambda 0 码力 | 82 页 | 12.15 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
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 constexpr :强迫编译器在编译期求值 结论:如果发现编译器放弃了自动优化,可以 用 constexpr 函数迫使编译器进行常量折叠! 不过, constexpr 函数中无法使用非 constexpr 的容器: vector, map, set, string 等 …… constexpr :强迫编译器在编译期求值(续) 发现:会让编译变得很慢,因为这 50000 次迭代是在编译期进行的。 第 20 码力 | 108 页 | 9.47 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 02 现代 C++ 入门:RAII 内存管理课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: ](https://git-scm.com/doc) - [GitHub 官方文档 ](https://docs.github.com/en) 古代: C 语言 近代: C++98 引入 STL 容器库 近现代: C++11 引入了 {} 初始化表达式 近现代: C++11 引入了 range-based for-loop 如果想使用 for_each 这个算法模板呢? 我知道可以用 accumulate 据等。 RAII 解决内存管理的问题: unique_ptr • 似曾相识的情形……是的,和我们刚刚提 到的 RAII 思想不谋而合! • 因此, C++11 引入了 unique_ptr 容器, 他的解构函数中会调用 delete p ,因此不 会有马虎犯错的问题。 • 这里 make_unique(...) 可以理解为和 之前的 new C(...) 等价,括号里也可以有 0 码力 | 96 页 | 16.28 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 12 从计算机组成原理看 C 语言指针,因为堆内存不会自动释放。 太复杂了?没关系,用 C++ 的容器库 • 如果你觉得这样自己管理内存太麻烦了,那是 正常的。对于不精通 C 语言的小白程序员来 说,很容易就忘记释放内存了。 • 因此 C++ 提供了符合 RAII 思想的 vector 容器,他会在自己解构时自动释放内存。 • 小白程序员只需要保证自己总是在用 C++ 封 装好的容器而不是 C 语言指针,就可以基本 保证没有内存泄露。但是封装的太好了也有效 保证没有内存泄露。但是封装的太好了也有效 率问题,因此追求极致性能时还是会直接操作 原始的 C 语言指针。此外如果不理解容器的 底层原理也很容易犯错,因此我们还是要好好 学习 C 语言思想的。 C 语言特性:函数声明为 T [] 类型的参数,实际上是 T * 类型 • 如果函数参数类型形如 • func(int arr[]) • func(int arr[6]) • 那么他其实就等价于: • 字符串实际上需要长度为 11 的字符数组 ! • 所以要把 str 声明为长度 11 的数组才行 。 C++ 的 string 容器 • 如果你搞不懂 C 语言硬核的 0 结尾字符 串,但还是害怕会发生内存越界的错误。 • 可以用 C++ 封装好的 string 容器和 cin 标准输入流。 cin 支持泛型, string 支持 自动扩容,符合 RAII 思想,可以避免小 白程序员犯错。0 码力 | 128 页 | 2.95 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 06 TBB 开启的并行编程之旅课程大纲 • 分为前半段和后半段,前半段主要介绍现代 C++ ,后半段主要介绍并行编程与优化。 1.课程安排与开发环境搭建: cmake 与 git 入门 2.现代 C++ 入门:常用 STL 容器, RAII 内存管理 3.现代 C++ 进阶:模板元编程与函数式编程 4.编译器如何自动优化:从汇编角度看 C++ 5.C++11 起的多线程编程:从 mutex 到无锁并行 6.并行编程常用框架: 且都是最近访问过的,从而已经在缓存里可以 直接读写,避免了从主内存读写的超高延迟。 • 下次课会进一步深入探讨访存优化,详细剖析 这个案例,那么下周六 14 点敬请期待。 第 6 章:并发容器 std::vector 扩容时会移动元素 • std::vector 内部存储了一个指针,指向一段容量 capacity 大于等于其 size 的内存。 • 众所周知, push_back 个元素, * 运算符访问当前指 向的元素。 可安全地被多线程并发访问 • 除了内存不连续、指针和迭代器不失效的 特点, tbb::concurrent_vector 还是一个多 线程安全的容器,能够被多个线程同时并 发地 grow_by 或 push_back 而不出错 。 • 而 std::vector 只有只读的 .size() 和 [] 运算符是安全的,且不能和写入的0 码力 | 116 页 | 15.85 MB | 1 年前3
共 20 条
- 1
- 2













