c++
文章平均质量分 92
c++
_Rye_
左手代码右手诗
一行代码一行诗
展开
-
33|性能测试的正确姿势:性能、时间和优化
假如我们有一个 int 类型的变量 x,那 x * 2 / 2 的结果是几?如果 C++ 把有符号整数运算溢出的结果定义为补码的内存表示,也就是说,32 位正整数 0x40'00'00'00(2^30)乘以 2 的结果就是 0x80'00'00'00(−2^31),再除以 2 的话,我们就不能得回原先的数值,而是得到了 0xC0'00'00'00(−2^30)。这样的话,x * 2 / 2 就不能优化为 x!那能不能使用异常呢?也不行。跟除零不一样,整数运算溢出不会产生硬件中断。原创 2023-10-11 20:27:58 · 28 阅读 · 0 评论 -
34|快速分配和释放内存:内存池
在第 31 讲我提到过,利用同一类型的对象的大小完全相同这一特性,可以实现一个高度优化的内存池。只是利用类特定的分配和释放函数,使用场景会比较受限。下面我会描述利用这个思路实现的一个内存池,既可以用在类特定的分配和释放函数里,也可以用在容器的分配器里。基本策略作为内存池,最基本的要求就是减少向系统的内存分配器请求内存的次数。因此,我们希望单次内存分配就获得大块的内存(chunk),然后分割开给各个对象使用。这样的内存块,通常是某个特定大小的整数倍。原创 2023-10-11 20:44:40 · 55 阅读 · 0 评论 -
32|容器里的内存管理:分配器
上一讲里我们讨论了 C++ 里内存管理的基本工具,分配和释放函数。今天,我们来讨论一下容器里管理内存的机制——分配器(allocator)。原创 2023-10-11 19:55:25 · 30 阅读 · 0 评论 -
31|new和delete背后:分配函数和释放函数
不过,业界的惯性是巨大的。比如,在 Linux 上标准库的分配和释放函数由 libstdc++.so 共享库提供,只要链接过程中在 -lstdc++ 之前的目标文件或库文件里有分配和释放函数出现,它们就会比标准库的分配和释放函数有更高的优先权,会被所有用到分配和释放函数的地方调用,包括 libstdc++ 自身。我们完全可以只对某一个类(如 Obj)替换它的分配和释放函数,这样,只有 new Obj 和 delete pObj 这样的表达式才会使用对应的分配和释放函数。但这远不是这两个函数的所有形式。原创 2023-10-11 18:19:41 · 51 阅读 · 0 评论 -
30 | Coroutines:协作式的交叉调度执行
协程是一个很早就被提出的编程概念。根据高德纳的描述,协程的概念在 1958 年就被提出了。不过,它在主流编程语言中得到的支持不那么好,因而你很可能对它并不熟悉吧。如果查阅维基百科,你可以看到下面这样的定义 :协程是计算机程序的⼀类组件,推⼴了协作式多任务的⼦程序,允许执⾏被挂起与被恢复。相对⼦例程⽽⾔,协程更为⼀般和灵活……等学完了这一讲,也许你可以明白这段话的意思。但对不了解协程的人来说,估计只能吐槽一句了,这是什么鬼?很遗憾,在 C++ 里的标准协程有点小复杂。我们还是从……Python 开始。原创 2023-10-11 17:44:59 · 45 阅读 · 0 评论 -
29 | Ranges:无迭代器的迭代和更方便的组合
int main()你应该已经见到过好多次了。有没有觉得这个代码有点重复、有点无聊呢?尤其是里面的 begin 和 end?很多人都留意到了迭代器虽然灵活,但不是一个足够高级的抽象——尤其是我们已经对 C 数组都可以进行基于“范围”的循环之后。这是真正可以编译的代码,用我们上一讲讲过的环境——最新版的 MSVC(编译命令行上需要额外加 /permissive- 选项)或 GCC 7+——都可以。原创 2023-10-11 17:23:22 · 56 阅读 · 0 评论 -
27 | C++ REST SDK:使用现代C++开发网络应用
有了初步印象之后,现在我们可以回过头看看 C++ REST SDK 到底是什么了。它是一套用来开发 HTTP 客户端和服务器的现代异步 C++ 代码库,支持以下特性(随平台不同会有所区别):HTTP 客户端HTTP 服务器任务JSONURI异步流WebSocket 客户端OAuth 客户端上面的例子里用到了 HTTP 客户端、任务和 URI(实际上是由 string_t 隐式构造了 uri),我们下面再介绍一下异步流、JSON 和 HTTP 服务器。异步流。原创 2023-10-11 15:08:10 · 422 阅读 · 0 评论 -
28 | Concepts:如何对模板进行约束?
从这一讲开始,我们进入了未来篇,展望一下即将在 C++20 出现的新功能。我们第一个要讨论的,是 concepts(概念)——一个难产了很多年才终于进入 C++ 的新功能。原创 2023-10-11 16:40:36 · 30 阅读 · 0 评论 -
26 | Easylogging++和spdlog:两个好用的日志库
Easylogging++ 一共只有两个文件,一个是头文件,一个是普通 C++ 源文件。事实上,它的一个较早版本只有一个文件。正如 Catch2 里一旦定义了 CATCH_CONFIG_MAIN 编译速度会大大减慢一样,把什么东西都放一起最终证明对编译速度还是相当不利的,因此,有人提交了一个补丁,把代码拆成了两个文件。使用 Easylogging++ 也只需要这两个文件——除此之外,就只有对标准和系统头文件的依赖了。要使用 Easylogging++,推荐直接把这两个文件放到你的项目里。原创 2023-10-11 10:42:12 · 322 阅读 · 0 评论 -
25 | 两个单元测试库:C++里如何进行单元测试?
单元测试已经越来越成为程序员工作密不可分的一部分了。在 C++ 里,我们当然也是可以很方便地进行单元测试的。今天,我就来介绍两个单元测试库:一个是 Boost.Test ,一个是 Catch2。原创 2023-10-11 10:17:29 · 104 阅读 · 0 评论 -
24 | Boost:你需要的“瑞士军刀”
我们已经零零碎碎提到过几次 Boost 了。作为 C++ 世界里标准库之外最知名的开放源码程序库,我们值得专门用一讲来讨论一下 Boost。原创 2023-10-11 10:01:31 · 53 阅读 · 0 评论 -
23 | 数字计算:介绍线性代数和数值计算库
科学计算在今天已经完全可以使用 C++ 了。我不是从事科学计算这一领域的工作的,不过,在工作中也多多少少接触到了一些计算相关的库。今天,我就给你介绍几个有用的计算库。说到计算,你可能首先会想到矩阵、矢量这些东西吧?这些计算,确实就是科学计算中的常见内容了。这些领域的标准,即是一些 Fortran 库定下的,如:BLASLAPACKARPACK它们的实现倒不一定用 Fortran,尤其是 BLAS:OpenBLAS 是用汇编和 C 语言写的。原创 2023-10-11 09:15:12 · 116 阅读 · 0 评论 -
22 | 处理数据类型变化和错误:optional、variant、expected和Herbception
我们之前已经讨论了异常是推荐的 C++ 错误处理方式。不过,C++ 里有另外一些结构也很适合进行错误处理,今天我们就来讨论一下。在面向对象(引用语义)的语言里,我们有时候会使用空值 null 表示没有找到需要的对象。也有人推荐使用一个特殊的空对象,来避免空值带来的一些问题。可不管是空值,还是空对象,对于一个返回普通对象(值语义)的 C++ 函数都是不适用的——空值和空对象只能用在返回引用 / 指针的场合,一般情况下需要堆内存分配,在 C++ 里会引致额外的开销。原创 2023-10-10 23:48:00 · 38 阅读 · 0 评论 -
21 | 工具漫谈:编译、格式化、代码检查、排错各显身手
现代 C++ 语言,我们讲到这里就告一段落了。今天我们正式开启了实战篇,先讲一个轻松些的话题——工具。原创 2023-10-10 23:47:28 · 101 阅读 · 0 评论 -
20 | 内存模型和atomic:理解并发的复杂性
上一讲我们讨论了一些并发编程的基本概念,今天我们来讨论一个略有点绕的问题,C++ 里的内存模型和原子量。原创 2023-10-10 23:46:43 · 82 阅读 · 0 评论 -
19 | thread和future:领略异步中的未来
编译期的烧脑我们先告个段落,今天我们开始讲一个全新的话题——并发(concurrency)。原创 2023-10-10 23:45:59 · 61 阅读 · 0 评论 -
18 | 应用可变模板和tuple的编译期技巧
今天我们讲一个特殊的专题,如何使用可变模板和 tuple 来完成一些常见的功能,尤其是编译期计算。原创 2023-10-10 23:45:21 · 27 阅读 · 0 评论 -
17 | 函数式编程:一种越来越流行的编程范式
上一讲我们初步介绍了函数对象和 lambda 表达式,今天我们来讲讲它们的主要用途——函数式编程。原创 2023-10-10 23:44:28 · 47 阅读 · 0 评论 -
16 | 函数对象和lambda:进入函数式编程
本讲我们将介绍函数对象,尤其是匿名函数对象——lambda 表达式。今天的内容说难不难,但可能跟你的日常思维方式有较大的区别,建议你一定要试验一下文中的代码(使用 xeus-cling 的同学要注意:xeus-cling 似乎不太喜欢有 lambda 的代码😓;遇到有问题时,还是只能回到普通的编译执行方式了)。原创 2023-10-10 18:33:20 · 29 阅读 · 0 评论 -
15 | constexpr:一个常态的世界
我们已经连续讲了几讲比较累人的编译期编程了。今天我们还是继续这个话题,但是,相信今天学完之后,你会感觉比之前几讲要轻松很多。C++ 语言里的很多改进,让我们做编译期编程也变得越来越简单了。原创 2023-10-10 17:30:14 · 73 阅读 · 0 评论 -
14 | SFINAE:不是错误的替换失败是怎么回事?
我们已经连续讲了两讲模板和编译期编程了。今天我们还是继续这个话题,讲的内容是模板里的一个特殊概念——替换失败非错(substitution failure is not an error),英文简称为 SFINAE。原创 2023-10-10 17:11:47 · 46 阅读 · 0 评论 -
13 | 编译期能做些什么?一个完整的计算世界
上一讲我们简单介绍了模板的基本用法及其在泛型编程中的应用。这一讲我们来看一下模板的另外一种重要用途——编译期计算,也称作“模板元编程”。原创 2023-10-10 16:51:40 · 31 阅读 · 0 评论 -
12 | 编译期多态:泛型编程和模板入门
相信你对多态这个面向对象的特性应该是很熟悉了。我们今天来讲一个非常 C++ 的话题,编译期多态及其相关的 C++ 概念。在面向对象的开发里,最基本的一个特性就是“多态” ——用相同的代码得到不同结果。以我们在[第 1 讲] 提到过的 shape 类为例,它可能会定义一些通用的功能,然后在子类里进行实现或覆盖:上面的类定义意味着所有的子类必须实现 draw 函数,所以可以认为 shape 是定义了一个接口(按 Java 的概念)。在面向对象的设计里,接口抽象了一些基本的行为,实现类里则去具体实现这些功能原创 2023-10-10 16:28:56 · 27 阅读 · 0 评论 -
11 | Unicode:进入多文字支持的世界
Unicode 在今天已经大大超出了最初的目标。到 Unicode 12.1 为止,Unicode 已经包含了 137,994 个字符,囊括所有主要语言(使用中的和已经不再使用的),并包含了表情符号、数学符号等各种特殊字符。仍然要指出一下,Unicode 字符是根据含义来区分的,而非根据字形。除了前面提到过中日韩汉字没有分开,像斜体(italics)、小大写字母(small caps)等排版效果在 Unicode 里也没有独立的对应。原创 2023-10-10 15:44:38 · 64 阅读 · 0 评论 -
10 | 到底应不应该返回对象?
前几讲里我们已经约略地提到了返回对象的问题,本讲里我们进一步展开这个话题,把返回对象这个问题讲深讲透。F.20《C++ 核心指南》的 F.20 这一条款是这么说的 :翻译一下:在函数输出数值时,尽量使用返回值而非输出参数这条可能会让一些 C++ 老手感到惊讶——在 C++11 之前的实践里,我们完全是采用相反的做法的啊!在解释 F.20 之前,我们先来看看我们之前的做法。原创 2023-10-10 11:39:55 · 61 阅读 · 0 评论 -
09 | 易用性改进 II:字面量、静态断言和成员函数说明符
字面量(literal)是指在源代码中写出的固定常量,它们在 C++98 里只能是原生类型,如:"hello",字符串字面量,类型是 const char[6]1,整数字面量,类型是 int0.0,浮点数字面量,类型是 double3.14f,浮点数字面量,类型是 float123456789ul,无符号长整数字面量,类型是 unsigned longC++11 引入了自定义字面量,可以使用 operator"" 后缀 来将用户提供的字面量转换成实际的类型。原创 2023-10-10 10:42:07 · 34 阅读 · 0 评论 -
08 | 易用性改进 I:自动类型推断和初始化
在之前的几讲里,我们已经多多少少接触到了一些 C++11 以来增加的新特性。下面的两讲,我会重点讲一下现代 C++(C++11/14/17)带来的易用性改进。原创 2023-10-10 08:52:27 · 27 阅读 · 0 评论 -
07 | 迭代器和好用的新for循环
迭代器是一个很通用的概念,并不是一个特定的类型。它实际上是一组对类型的要求。它的最基本要求就是从一个端点出发,下一步、下一步地到达另一个端点。按照一般的中文习惯,也许“遍历”是比“迭代”更好的用词。我们可以遍历一个字符串的字符,遍历一个文件的内容,遍历目录里的所有文件,等等。这些都可以用迭代器来表达。我在用 output_container.h 输出容器内容的时候,实际上就对容器的 begin 和 end 成员函数返回的对象类型提出了要求。原创 2023-10-09 20:14:08 · 140 阅读 · 0 评论 -
06 | 异常:用还是不用,这是个问题
到现在为止,我们已经有好多次都提到异常了。今天,我们就来彻底地聊一聊异常。首先,开宗明义,如果你不知道到底该不该用异常的话,那答案就是该用。如果你需要避免使用异常,原因必须是你有明确的需要避免使用异常的理由。下面我们就开始说说异常。原创 2023-10-09 17:43:38 · 26 阅读 · 0 评论 -
05 | 容器汇编 II:需要函数对象的容器
上一讲我们学习了 C++ 的序列容器和两个容器适配器,今天我们继续讲完剩下的标准容器。原创 2023-10-09 17:25:51 · 22 阅读 · 0 评论 -
04 | 容器汇编 I:比较简单的若干容器
上几讲我们学习了 C++ 的资源管理和值类别。今天我们换一个话题,来看一下 C++ 里的容器。关于容器,已经存在不少的学习资料了。在 cppreference 上有很完备的参考资料([1])。今天我们采取一种非正规的讲解方式,尽量不重复已有的参考资料,而是让你加深对于重要容器的理解。对于容器,学习上的一个麻烦点是你无法直接输出容器的内容——如果你定义了一个 vector<int> v,你是没法简单输出 v 的内容的。原创 2023-10-09 15:45:09 · 29 阅读 · 0 评论 -
03 | 右值和移动究竟解决了什么问题?
从上一讲智能指针开始,我们已经或多或少接触了移动语义。本讲我们就完整地讨论一下移动语义和相关的概念。移动语义是 C++11 里引入的一个重要概念;理解这个概念,是理解很多现代 C++ 里的优化的基础。原创 2023-10-09 15:06:41 · 33 阅读 · 0 评论 -
02 | 自己动手,实现C++的智能指针
上一讲,我们描述了一个某种程度上可以当成智能指针用的类 shape_wrapper。使用那个智能指针,可以简化资源的管理,从根本上消除资源(包括内存)泄漏的可能性。这一讲我们就来进一步讲解,如何将 shape_wrapper 改造成一个完整的智能指针。你会看到,智能指针本质上并不神秘,其实就是 RAII 资源管理功能的自然展现而已。在学完这一讲之后,你应该会对 C++ 的 unique_ptr 和 shared_ptr 的功能非常熟悉了。同时,如果你今后要创建类似的资源管理类,也不会是一件难事。原创 2023-10-09 14:28:14 · 49 阅读 · 0 评论 -
01 | 堆、栈、RAII:C++里该如何管理资源?
今天我们就正式开启了 C++ 的学习之旅,作为第一讲,我想先带你把地基打牢。我们来学习一下内存管理的基本概念,大致的学习路径是:先讲堆和栈,然后讨论 C++ 的特色功能 RAII。掌握这些概念,是能够熟练运用 C++ 的基础。原创 2023-10-09 11:24:36 · 39 阅读 · 0 评论