现代C++ 教程:高速上手C++11/14/17/20门,所有这些新标准中扩充的特性,给 C++ 这门语言注入了新的活力。那些还在坚持使用传统 C++ (本书把 C++98 及其之前的 C++ 特性均称之为传统 C++)而未接触过现代 C++ 的 C++ 程序员在 见到诸如 Lambda 表达式这类全新特性时,甚至会流露出『学的不是同一门语言』的惊叹之情。 现代 C++ (本书中均指 C++11/14/17/20) 为传统 C++ 注入的大量特性使得整个 C++ 变得更加 具有了『匿名函数』的『闭包』特性,而这一特性几乎在现代的编程语言(诸如 Python/Swift/. . . )中已经司空见惯,右值引用的出现解决了 C++ 长期以来被人诟病的临时对象效率问题等等。 C++17 则是近三年依赖 C++ 社区一致推进的方向,也指出了 现代 C++ 编程的一个重要发展方 向。尽管它的出现并不如 C++11 的分量之重,但它包含了大量小而美的语言与特性(例如结构化绑定), 这些特性的出现再一次修正了我们在 这些特性的出现再一次修正了我们在 C++ 中的编程范式。 现代 C++ 还为自身的标准库增加了非常多的工具和方法,诸如在语言自身标准的层面上制定了 std::thread,从而支持了并发编程,在不同平台上不再依赖于系统底层的 API,实现了语言层面的跨 平台支持;std::regex 提供了完整的正则表达式支持等等。C++98 已经被实践证明了是一种非常成功 的『范型』,而现代 C++ 的出现,则进一步推动这种范型,让0 码力 | 83 页 | 2.42 MB | 1 年前3
Hello 算法 1.2.0 简体中文 C++ 版。 第 1 章 初识算法 www.hello‑algo.com 11 1.1 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面我将举几个具体的例子来证实这一点。 数据结构与算法的关系 如图 1‑4 所示,数据结构与算法高度相关、紧密结合,具体表现在以下三个方面。 ‧ 数据结构是算法的基石。数据结构为算法提供了结构化存储的数据,以及操作数据的方法。 ‧ 算法为数据结构注入生命力。数据结构本身仅存储数据信息,结合算法才能解决特定问题。 ‧ 算法通常可以基于不同的数据结构实现,但执行效率可能相差很大,选择合适的数据结构是关键。 图 1‑4 数据结构与算法的关系 数据结构与算法犹如图 取当前看来最好的选择。 ‧ 算法是在有限时间内解决特定问题的一组指令或操作步骤,而数据结构是计算机中组织和存储数据的 方式。 ‧ 数据结构与算法紧密相连。数据结构是算法的基石,而算法为数据结构注入生命力。 ‧ 我们可以将数据结构与算法类比为拼装积木,积木代表数据,积木的形状和连接方式等代表数据结构, 拼装积木的步骤则对应算法。 1. Q & A Q:作为一名程序员,我在日常工作中从未0 码力 | 379 页 | 18.48 MB | 10 月前3
C++高性能并行编程与优化 - 课件 - 01 学 C++ 从 CMake 学起文件越来越多时,一个个调用 g++ 编译链接会变得很麻烦。 • 于是,发明了 make 这个程序,你只需写出不同文件之间的依赖关系,和生成各文件的规则。 • > make a.out • 敲下这个命令,就可以构建出 a.out 这个可执行文件了。 • 和直接用一个脚本写出完整的构建过程相比, make 指明依赖关系的好处: 1. 当更新了 hello.cpp 时只会重新编译 hello.o ,而不需要把 main o 重复写 g++ 命令( %.o: %.cpp )。 • 但坏处也很明显: 1. make 在 Unix 类系统上是通用的,但在 Windows 则不然。 2. 需要准确地指明每个项目之间的依赖关系,有头文件时特别头疼。 3. make 的语法非常简单,不像 shell 或 python 可以做很多判断等。 4. 不同的编译器有不同的 flag 规则,为 g++ 准备的参数可能对 MSVC Windows 则不然。 • 只需要写一份 CMakeLists.txt ,他就能够在调用时生成当前系统所支持的构建系统。 • 需要准确地指明每个项目之间的依赖关系,有头文件时特别头疼。 • CMake 可以自动检测源文件和头文件之间的依赖关系,导出到 Makefile 里。 • make 的语法非常简单,不像 shell 或 python 可以做很多判断等。 • CMake 具有相对高级的语法,内置的函数能够处理0 码力 | 32 页 | 11.40 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 08 CUDA 开启的 GPU 编程循环迭代所有 1024 个元 素,实际上内部仍然是一个串行的过程,数据是强烈 依赖的( local_sum += arr[j] 可以体现出,下一时刻 的 local_sum 依赖于上一时刻的 local_sum )。 • 要消除这种依赖,可以通过右边这样的逐步缩减,这 样每个 for 循环内部都是没有数据依赖,从而是可以 并行的(对 CPU 而言是 SIMD 和指令级并行,虽 然 GPU 循环迭代所有 1024 个元 素,实际上内部仍然是一个串行的过程,数据是强烈 依赖的( local_sum += arr[j] 可以体现出,下一时刻 的 local_sum 依赖于上一时刻的 local_sum )。 • 要消除这种依赖,可以通过右边这样的逐步缩减,这 样每个 for 循环内部都是没有数据依赖,从而是可以 并行的(对 CPU 而言是 SIMD 和指令级并行,虽 然 GPU GPU 没有,但为了引出共享内存的概念我才这样 改)。 板块的共享内存( shared memory ) • 刚刚已经实现了无数据依赖可以并行的 for ,那么如何把 他真正变成并行的呢?这就是板块的作用了,我们可以把 刚刚的线程升级为板块,刚刚的 for 升级为线程,然后把 刚刚 local_sum 这个线程局部数组升级为板块局部数组。 那么如何才能实现板块局部数组呢? • 同一个板0 码力 | 142 页 | 13.52 MB | 1 年前3
C++高性能并行编程与优化 - 课件 - 16 现代 CMake 模块化项目管理指南关键 字。 八、每新增一个功能模块,需要创建两个文件 • 添加一个新功能模块 Carer 时,同时添加同名的源文件和头文 件。 • 头文件中的声明和源文件中的实现一一对应。 九、一个模块依赖其他模块,则应导入他的头文件 • 如果新模块( Carer )中用到了其他模块( Animal )的类或函数,则需要 在新模块( Carer )的头文件和源文件中都导入其他模块( Animal )的头 注意不论是项目自己的头文件还是外部的系统的头文件,请全部统一采用 < 项目名 / 模块名 .h> 的格式。不要用 “模块名 .h” 这种相对路径的格式,避 免模块名和系统已有头文件名冲突。 十、依赖其他模块但不解引用,则可以只前向声明不导入头文件 • 如果模块 Carer 的头文件 Carer.h 虽然引用了其他模块中的 Animal 类,但 是他里面并没有解引用 Animal ,只有源文件 ,两个符号就会发生冲突,由于类符号 都具有 weak 属性,链接器会随机选择一个覆盖掉,非常危险! • (关于符号的 weak 属性,以后单独开一门 C++ 课讲讲,这一课还是重点关注 CMake ) 十二、依赖另一个子项目,则需要链接他 • 让 pybmain 链接上 biology : target_link_libraries(pybmain PUBLIC biology) • 由于 PUBLIC0 码力 | 56 页 | 6.87 MB | 1 年前3
Hello 算法 1.0.0b4 C++版本书网页版的每个章节都设有讨论区,欢迎随时分享你的疑惑与见解。 7 1. 初识算法 1.1. 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖于基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面,我将举几个具体例子来证实这一点。 大。 哈希查找 ‧ 适合对查询性能要求很高的场景,平均时间复杂度为 ?(1) 。 ‧ 不适合需要有序数据或范围查找的场景,因为哈希表无法维护数据的有序性。 ‧ 对哈希函数和哈希冲突处理策略的依赖性较高,具有较大的性能劣化风险。 ‧ 不适合数据量过大的情况,因为哈希表需要额外空间来最大程度地减少冲突,从而提供良好的查询性 能。 树查找 ‧ 适用于海量数据,因为树节点在内存中是离散存储的。 生倾斜,时间复杂度劣化至 ?(?) 。 ‧ 若使用 AVL 树或红黑树,则各项操作可在 ?(log ?) 效率下稳定运行,但维护树平衡的操作会增加额 外开销。 10.5. 小结 ‧ 二分查找依赖于数据的有序性,通过循环逐步缩减一半搜索区间来实现查找。它要求输入数据有序,且 仅适用于数组或基于数组实现的数据结构。 ‧ 暴力搜索通过遍历数据结构来定位数据。线性搜索适用于数组和链表,广度优先搜索和深度优先搜索0 码力 | 343 页 | 27.39 MB | 1 年前3
Hello 算法 1.1.0 C++ 版算法世界。 第 1 章 初识算法 hello‑algo.com 11 1.1 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面我将举几个具体的例子来证实这一点。 所示,在程序运行时,数据会从硬盘中被读取到内存中,供 CPU 计算使用。缓存可以看作 CPU 的 一部分,它通过智能地从内存加载数据,给 CPU 提供高速的数据读取,从而显著提升程序的执行效率,减少 对较慢的内存的依赖。 图 4‑10 硬盘、内存和缓存之间的数据流通 4.4.2 数据结构的内存效率 在内存空间利用方面,数组和链表各自具有优势和局限性。 一方面,内存是有限的,且同一块内存不能被多个程序共享, 大。 哈希查找 ‧ 适合对查询性能要求很高的场景,平均时间复杂度为 ?(1) 。 ‧ 不适合需要有序数据或范围查找的场景,因为哈希表无法维护数据的有序性。 ‧ 对哈希函数和哈希冲突处理策略的依赖性较高,具有较大的性能劣化风险。 ‧ 不适合数据量过大的情况,因为哈希表需要额外空间来最大程度地减少冲突,从而提供良好的查询性 能。 树查找 ‧ 适用于海量数据,因为树节点在内存中是分散存储的。0 码力 | 379 页 | 18.47 MB | 1 年前3
Hello 算法 1.0.0 C++版算法世界。 第 1 章 初识算法 hello‑algo.com 11 1.1 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面我将举几个具体的例子来证实这一点。 所示,在程序运行时,数据会从硬盘中被读取到内存中,供 CPU 计算使用。缓存可以看作 CPU 的 一部分,它通过智能地从内存加载数据,给 CPU 提供高速的数据读取,从而显著提升程序的执行效率,减少 对较慢的内存的依赖。 图 4‑10 硬盘、内存和缓存之间的数据流通 4.4.2 数据结构的内存效率 在内存空间利用方面,数组和链表各自具有优势和局限性。 一方面,内存是有限的,且同一块内存不能被多个程序共享, 大。 哈希查找 ‧ 适合对查询性能要求很高的场景,平均时间复杂度为 ?(1) 。 ‧ 不适合需要有序数据或范围查找的场景,因为哈希表无法维护数据的有序性。 ‧ 对哈希函数和哈希冲突处理策略的依赖性较高,具有较大的性能劣化风险。 ‧ 不适合数据量过大的情况,因为哈希表需要额外空间来最大程度地减少冲突,从而提供良好的查询性 能。 树查找 ‧ 适用于海量数据,因为树节点在内存中是分散存储的。0 码力 | 378 页 | 17.59 MB | 1 年前3
Hello 算法 1.2.0 繁体中文 C++ 版如圖 1‑4 所示,資料結構與演算法高度相關、緊密結合,具體表現在以下三個方面。 ‧ 資料結構是演算法的基石。資料結構為演算法提供了結構化儲存的資料,以及操作資料的方法。 ‧ 演算法為資料結構注入生命力。資料結構本身僅儲存資料資訊,結合演算法才能解決特定問題。 ‧ 演算法通常可以基於不同的資料結構實現,但執行效率可能相差很大,選擇合適的資料結構是關鍵。 圖 1‑4 資料結構與演算法的關係 來最好的選擇。 ‧ 演算法是在有限時間內解決特定問題的一組指令或操作步驟,而資料結構是計算機中組織和儲存資料 的方式。 ‧ 資料結構與演算法緊密相連。資料結構是演算法的基石,而演算法為資料結構注入生命力。 ‧ 我們可以將資料結構與演算法類比為拼裝積木,積木代表資料,積木的形狀和連線方式等代表資料結 構,拼裝積木的步驟則對應演算法。 1. Q & A Q:作為一名程式設計師,我在日常工0 码力 | 379 页 | 18.79 MB | 10 月前3
Hello 算法 1.0.0b5 C++版算法世界。 第 1 章 初识算法 hello‑algo.com 10 1.1 算法无处不在 当我们听到“算法”这个词时,很自然地会想到数学。然而实际上,许多算法并不涉及复杂数学,而是更多 地依赖于基本逻辑,这些逻辑在我们的日常生活中处处可见。 在正式探讨算法之前,有一个有趣的事实值得分享:你已经在不知不觉中学会了许多算法,并习惯将它们应 用到日常生活中了。下面,我将举几个具体例子来证实这一点。 大。 哈希查找 ‧ 适合对查询性能要求很高的场景,平均时间复杂度为 ?(1) 。 ‧ 不适合需要有序数据或范围查找的场景,因为哈希表无法维护数据的有序性。 ‧ 对哈希函数和哈希冲突处理策略的依赖性较高,具有较大的性能劣化风险。 ‧ 不适合数据量过大的情况,因为哈希表需要额外空间来最大程度地减少冲突,从而提供良好的查询性 能。 树查找 ‧ 适用于海量数据,因为树节点在内存中是离散存储的。 在持续增删节点的过程中,二叉搜索树可能产生倾斜,时间复杂度劣化至 ?(?) 。 ‧ 若使用 AVL 树或红黑树,则各项操作可在 ?(log ?) 效率下稳定运行,但维护树平衡的操作会增加额 外开销。 10.6 小结 ‧ 二分查找依赖于数据的有序性,通过循环逐步缩减一半搜索区间来实现查找。它要求输入数据有序,且 仅适用于数组或基于数组实现的数据结构。 ‧ 暴力搜索通过遍历数据结构来定位数据。线性搜索适用于数组和链表,广度优先搜索和深度优先搜索0 码力 | 377 页 | 30.69 MB | 1 年前3
共 20 条
- 1
- 2













