Dlyw

Dlyw 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 该用户太懒什么也没留下

个人动态

Dlyw 回答了问题 · 10月14日

解决在 PHP 中该如何使用 PurgeCSS?

https://github.com/spatie/lar... 看一下这个是不是能解决你的问题

关注 4 回答 2

Dlyw 赞了文章 · 10月9日

精选 22 个 C++ 项目,推荐新人练手首选!

C/C++ 作为元老级的编程语言,任时光更迭依旧屹立不倒,哪怕如今炙手可热的AI,其底层也是用其编写。

那么作为新手该如何快速上手 C++ 呢?当然是敲代码啊!一切不写代码的学编程都是瞎搞。下面为大家精选了 22 个 C++ 项目,推荐新人练手首选!

1.C++ 实现基数树

使用 C++ 实现Radix树:一种基于二进制表示的键值的查找树,尤其适合处理非常长的、可变长度的键值,Patricia 的基本思想是构建一个二叉树。

2.C++ 实现并行计算的K-Means聚类算法

使用 C++ 实现一个完整的面向对象的可并行K-Means算法。

3.C++ 实现 STL 标准库和算法

实现 C++ STL 的容器和算法的实现。

4.C++ 实现内存泄露检查器

内存泄漏一直是 C++ 中比较令人头大的问题, 即便是很有经验的 C++ 程序员有时候也难免因为疏忽而写出导致内存泄漏的代码。本项目使用 C++ 实现一个内存泄漏检查器。
image

5.C++ 实现高性能内存池

获得内存池所分配的内存速度高于从堆中获得分配的内存的速度,一个长期稳定运行的服务在追求极致的过程中,实现内存池是必不可少的。和标准库中的默认分配器一样,内存池本质上也是分配器,本项目设计并使用 C++实现一个高性能内存池。
image

6.C++ 实现高性能 RTTI 库

RTTI 是运行时类型识别的英文缩写,C++ 本身提供了运行时类型检查的运算符 dynamic_cast 和 typeid,然而 dynamic_cast 的效率其实并不理想,需要牺牲一定性能。本项目将使用 C++ 手动实现一个高性能 RTTI 库。
image

7.C++ 实现智能指针

使用C++语言实现智能指针的过程,来了解C++基本程序设计的方法,包括类的定义与使用,运算符的重载,模板类的使用方法,以及引用计数技术。

8.C++ 实现即时通信软件

使用 C++ 实现一个具备服务端和客户端的即时通信聊天室,涉及网络编程,C++面向对象程序设计等知识。

image

9.C++实现课程管理系统

使用C++ 实现一个课程管理系统,在这个过程中会介绍 C++ 11 的很多特性,同时可以熟悉 Linux下 的 C++ 。

10.C++ 实现银行排队服务模拟

使用 C++对银行排队服务进行模拟,以事件驱动为核心思想,手动实现模板链式队列、随机数产生器等内容,进而学习概率编程等知识。作为可选进阶,这个模型同时还能稍加修改的应用到 CPU 资源争夺模型中。

11.C++操作 redis 实现异步订阅和发布

操作 redis 实现异步订阅和发布,其中将介绍 redis 基础知识,在linux中安装和使用 redis ,常用的 hiredis API,并实现一个例程。

12.C++ 使用 openGL 实现吃豆人游戏

通过 C++ 和 openGL 库来实现了一个吃豆人的小游戏。使用了标准模板库,既对自己之前知识的检阅也是对 C++ 编程能力的一种提升。
image

13.C++ 解决迷宫问题

通过 C++ 实现了一个迷宫游戏,游戏不仅涉及到简单的 C++ 游戏思想,还涉及到深度优先遍历算法。

image

14.C++ 基于 OpenCV 实现实时监控和运动检测记录

使用 C++ 和 OpenCV 提供的库函数,实现摄像头的实时监控功能,并通过监控画面的运动检测选择是否记录视频。监控人员可选择输出图像的模式以更容易的分辨监控中的异常情况。

15.C++ 实现简易 Docker 容器

C++ 与 Linux 的 Namespace 及 Control Group 技术相结合,实现一个简易 Docker 容器。

16.C++ 开发 Web 服务框架

将综合使用 C++11 及 Boost 中的 Asio 实现 HTTP 和 HTTPS 的服务器框架。

17.C++ 编写 json 生成器

用 C++ 编写一个 json 生成器,生成 json 数据,并学习编写测试用例。

18.C++ 利用 QT 实现 PDF 阅读器

利用 QT 开发环境来实现一个 PDF 阅读器。主要内容包含了 QT 的基本用法以及图形界面的设计,还有第三方库 poppler 的使用。

image

19.C++17 自制脚本语言

使用 C++ 语言自制一个脚本语言。麻雀虽小五脏俱全,它完整支持函数,条件/位/逻辑运算,原生字符串/数组类型等特性。主要将从理论出发,逐步构建词法分析器,语法分析器,AST,运行时,最终实现一个完整的脚本语言,并且使用该脚本语言解决一些实际问题。

20.C++ 实现太阳系行星系统

使用 C++实现 OpenGL GLUT 实现一个简单的太阳系行星系统,将涉及一些三维图形技术的数学基础、OpenGL 里的三维坐标系、OpenGL 里的光照模型、GLUT 的键盘事件处理。

21.C++11 从零实现 NoSQL 数据库

使用 C++11 实现了一个完全兼容 redis 的 kv 数据库项目——Qedis;该项目会使用到一些 C++11 核心特性和 STL 库,并利用已有的 tcp 网络库,逐步构建出一个完全兼容 Redis 的更高性能的内存数据库。

22.C++ 实现 XML 解析

通过 C++ 实现 XML 文档内容解析,充分利用了 C++ 功能特性和泛型编程思想。通过本课程可以规范自己的编程习惯并积累大型项目开发经验。

知乎专栏同步:https://zhuanlan.zhihu.com/p/86779615

查看原文

赞 7 收藏 6 评论 0

Dlyw 收藏了文章 · 10月9日

C++ 常用库

标准库

C++标准库,包括了STL容器,算法和函数等。

框架

C++通用框架和库

  • Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合
  • ASL:Adobe源代码库提供了同行的评审和可移植的C++源代码库。
  • Boost:大量通用C++库的集合。
  • BDE:来自于彭博资讯实验室的开发环境。
  • Cinder:提供专业品质创造性编码的开源开发社区。
  • Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。
  • Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。
  • EASTL:EA-STL公共部分
  • ffead-cpp:企业应用程序开发框架
  • Folly:由Facebook开发和使用的开源C++库
  • JUCE:包罗万象的C++类库,用于开发跨平台软件
  • libPhenom:用于构建高性能和高度可扩展性系统的事件框架。
  • LibSourcey:用于实时的视频流和高性能网络应用程序的C++11 evented IO
  • LibU: C语言写的多平台工具库
  • Loki:C++库的设计,包括常见的设计模式和习语的实现。
  • MiLi:只含头文件的小型C++库
  • openFrameworks:开发C++工具包,用于创意性编码。
  • Qt:跨平台的应用程序和用户界面框架
  • Reason:跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。
  • ROOT:具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。
  • STLport:是STL具有代表性的版本
  • STXXL:用于额外的大型数据集的标准模板库。
  • Ultimate++:C++跨平台快速应用程序开发框架
  • Windows Template Library:用于开发Windows应用程序和UI组件的C++库
  • Yomm11:C++11的开放multi-methods.

人工智能

  • btsk:游戏行为树启动器工具
  • Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。
  • Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。

异步事件循环

  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库。
  • libev:功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。
  • libevent:事件通知库
  • libuv:跨平台异步I/O。

音频

音频,声音,音乐,数字化音乐库

  • FMOD:易于使用的跨平台的音频引擎和音频内容的游戏创作工具。
  • Maximilian:C++音频和音乐数字信号处理库
  • OpenAL:开源音频库—跨平台的音频API
  • Opus:一个完全开放的,免版税的,高度通用的音频编解码器
  • Speex:免费编解码器,为Opus所废弃
  • Tonic: C++易用和高效的音频合成
  • Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。

生态学

生物信息,基因组学和生物技术

  • libsequence:用于表示和分析群体遗传学数据的C++库。
  • SeqAn:专注于生物数据序列分析的算法和数据结构。
  • Vcflib:用于解析和处理VCF文件的C++库
  • Wham:直接把联想测试应用到BAM文件的基因结构变异。

压缩

压缩和归档库

  • bzip2:一个完全免费,免费专利和高质量的数据压缩
  • doboz:能够快速解压缩的压缩库
  • PhysicsFS:对各种归档提供抽象访问的库,主要用于视频游戏,设计灵感部分来自于Quake3的文件子系统。
  • KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。
  • LZ4:非常快速的压缩算法
  • LZHAM:无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。
  • LZMA:7z格式默认和通用的压缩方法。
  • LZMAT:及其快速的实时无损数据压缩库
  • miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。
  • Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。
  • Snappy:快速压缩和解压缩
  • ZLib:非常紧凑的数据流压缩库
  • ZZIPlib:提供ZIP归档的读权限。

并发性

并发执行和多线程

  • Boost.Compute:用于OpenCL的C++GPU计算库
  • Bolt:针对GPU进行优化的C++模板库
  • C++React:用于C++11的反应性编程库
  • Intel TBB:Intel线程构件块
  • Libclsph:基于OpenCL的GPU加速SPH流体仿真库
  • OpenCL:并行编程的异构系统的开放标准
  • OpenMP:OpenMP API
  • Thrust:类似于C++标准模板库的并行算法库
  • HPX:用于任何规模的并行和分布式应用程序的通用C++运行时系统
  • VexCL:用于OpenCL/CUDA 的C++向量表达式模板库。

容器

  • C++ B-tree:基于B树数据结构,实现命令内存容器的模板库
  • Hashmaps: C++中开放寻址哈希表算法的实现

密码学

  • Bcrypt:一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。
  • BeeCrypt
  • Botan: C++加密库
  • Crypto++:一个有关加密方案的免费的C++库
  • GnuPG: OpenPGP标准的完整实现
  • GnuTLS:实现了SSL,TLS和DTLS协议的安全通信库
  • Libgcrypt
  • libmcrypt
  • LibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支
  • LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具
  • libsodium:基于NaCI的加密库,固执己见,容易使用
  • Nettle底层的加密库
  • OpenSSL: 一个强大的,商用的,功能齐全的,开放源代码的加密库。
  • Tiny AES128 in C:用C实现的一个小巧,可移植的实现了AES128ESB的加密算法

数据库

数据库,SQL服务器,ODBC驱动程序和工具

  • hiberlite:用于Sqlite3的C++对象关系映射
  • Hiredis: 用于Redis数据库的很简单的C客户端库
  • LevelDB: 快速键值存储库
  • LMDB:符合数据库四大基本元素的嵌入键值存储
  • MySQL++:封装了MySql的C API的C++ 包装器
  • RocksDB:来自Facebook的嵌入键值的快速存储
  • SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。

调试

调试库, 内存和资源泄露检测,单元测试

  • Boost.Test:Boost测试库
  • Catch:一个很时尚的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。
  • CppUnit:由JUnit移植过来的C++测试框架
  • CTest:CMake测试驱动程序
  • googletest:谷歌C++测试框架
  • ig-debugheap:用于跟踪内存错误的多平台调试堆
  • libtap:用C语言编写测试
  • MemTrack—用于C++跟踪内存分配
  • microprofile- 跨平台的网络试图分析器
  • minUnit:使用C写的迷你单元测试框架,只使用了两个宏
  • Remotery:用于web视图的单一C文件分析器
  • UnitTest++:轻量级的C++单元测试框架

游戏引擎

  • Cocos2d-x:一个跨平台框架,用于构建2D游戏,互动图书,演示和其他图形应用程序。
  • Grit:社区项目,用于构建一个免费的游戏引擎,实现开放的世界3D游戏。
  • Irrlicht:C++语言编写的开源高性能的实时#D引擎
  • Polycode:C++实现的用于创建游戏的开源框架(与Lua绑定)。

图形用户界面

  • CEGUI: 很灵活的跨平台GUI库
  • FLTK:快速,轻量级的跨平台的C++GUI工具包。
  • GTK+: 用于创建图形用户界面的跨平台工具包
  • gtkmm:用于受欢迎的GUI库GTK+的官方C++接口。
  • imgui:拥有最小依赖关系的立即模式图形用户界面
  • libRocketlibRocket是一个C++ HTML/CSS 游戏接口中间件
  • MyGUI:快速,灵活,简单的GUI
  • Ncurses:终端用户界面
  • QCustomPlot:没有更多依赖关系的Qt绘图控件
  • Qwt:用户与技术应用的Qt 控件
  • QwtPlot3D:功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件
  • OtterUIOtterUI是用于嵌入式系统和互动娱乐软件的用户界面开发解决方案
  • PDCurses包含源代码和预编译库的公共图形函数库
  • wxWidgetsC++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序

图形

  • bgfx:跨平台的渲染库
  • Cairo:支持多种输出设备的2D图形库
  • Horde3D一个小型的3D渲染和动画引擎
  • magnumC++11和OpenGL 2D/3D 图形引擎
  • Ogre 3D用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非游戏引擎)
  • OpenSceneGraph具有高性能的开源3D图形工具包
  • Panda3D用于3D渲染和游戏开发的框架,用Python和C++编写。
  • Skia用于绘制文字,图形和图像的完整的2D图形库
  • urho3d跨平台的渲染和游戏引擎。

图像处理

  • Boost.GIL:通用图像库
  • CImg:用于图像处理的小型开源C++工具包
  • CxImage:用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
  • FreeImage:开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
  • GDCM:Grassroots DICOM 库
  • ITK:跨平台的开源图像分析系统
  • Magick++:ImageMagick程序的C++接口
  • MagickWnd:ImageMagick程序的C++接口
  • OpenCV: 开源计算机视觉类库
  • tesseract-ocr:OCR引擎
  • VIGRA:用于图像分析通用C++计算机视觉库
  • VTK:用于3D计算机图形学,图像处理和可视化的开源免费软件系统。

国际化

  • gettext:GNU `gettext’
  • IBM ICU:提供Unicode 和全球化支持的C、C++ 和Java库
  • libiconv:用于不同字符编码之间的编码转换库

Jason

  • frozen: C/C++的Jason解析生成器
  • Jansson:进行编解码和处理Jason数据的C语言库
  • jbson:C++14中构建和迭代BSON data,和Json 文档的库
  • JeayeSON:非常健全的C++ JSON库,只包含头文件
  • JSON++: C++ JSON 解析器
  • json-parser:用可移植的ANSI C编写的JSON解析器,占用内存非常少
  • json11:一个迷你的C++11 JSON库
  • jute:非常简单的C++ JSON解析器
  • ibjson:C语言中的JSON解析和打印库,很容易和任何模型集成。
  • libjson:轻量级的JSON库
  • PicoJSON:C++中JSON解析序列化,只包含头文件
  • qt-json:用于JSON数据和 QVariant层次间的相互解析的简单类
  • QJson:将JSON数据映射到QVariant对象的基于Qt的库
  • RapidJSON: 用于C++的快速JSON 解析生成器,包含SAX和DOM两种风格的API
  • YAJL:C语言中快速流JSON解析库

日志

  • Boost.Log:设计非常模块化,并且具有扩展性
  • easyloggingpp:C++日志库,只包含单一的头文件。
  • Log4cpp:一系列C++类库,灵活添加日志到文件,系统日志,IDSA和其他地方。
  • templog:轻量级C++库,可以添加日志到你的C++应用程序中

机器学习

  • Caffe:快速的神经网络框架
  • CCV:以C语言为核心的现代计算机视觉库
  • mlpack:可扩展的C++机器学习库
  • OpenCV:开源计算机视觉库
  • Recommender:使用协同过滤进行产品推荐/建议的C语言库。
  • SHOGUN:Shogun 机器学习工具
  • sofia-ml:用于机器学习的快速增量算法套件

数学

  • Armadillo:高质量的C++线性代数库,速度和易用性做到了很好的平衡。语法和MatlAB很相似
  • blaze:高性能的C++数学库,用于密集和稀疏算法。
  • ceres-solver:来自谷歌的C++库,用于建模和解决大型复杂非线性最小平方问题。
  • CGal: 高效,可靠的集合算法集合
  • cml:用于游戏和图形的免费C++数学库
  • Eigen:高级C++模板头文件库,包括线性代数,矩阵,向量操作,数值解决和其他相关的算法。
  • GMTL:数学图形模板库是一组广泛实现基本图形的工具。
  • GMP:用于个高精度计算的C/C++库,处理有符号整数,有理数和浮点数。

多媒体

  • GStreamer:构建媒体处理组件图形的库
  • LIVE555 Streaming Media:使用开放标准协议(RTP/RTCP, RTSP, SIP) 的多媒体流库
  • libVLC:libVLC (VLC SDK)媒体框架
  • QtAv:基于Qt和FFmpeg的多媒体播放框架,能够帮助你轻而易举地编写出一个播放器
  • SDL:简单直控媒体层
  • SFML:快速,简单的多媒体库

网络

  • ACE:C++面向对象网络变成工具包
  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库
  • Casablanca:C++ REST SDK
  • cpp-netlib:高级网络编程的开源库集合
  • Dyad.c:C语言的异步网络
  • libcurl:多协议文件传输库
  • Mongoose<span style="text-decoration: underline;">:</span>非常轻量级的网络服务器
  • Muduo:用于Linux多线程服务器的C++非阻塞网络库
  • net_skeleton:C/C++的TCP 客户端/服务器库
  • nope.c:基于C语言的超轻型软件平台,用于可扩展的服务器端和网络应用。 对于C编程人员,可以考虑node.js
  • Onion:C语言HTTP服务器库,其设计为轻量级,易使用。
  • POCO:用于构建网络和基于互联网应用程序的C++类库,可以运行在桌面,服务器,移动和嵌入式系统。
  • RakNet:为游戏开发人员提供的跨平台的开源C++网络引擎。
  • Tuf o:用于Qt之上的C++构建的异步Web框架。
  • WebSocket++:基于C++/Boost Aiso的websocket 客户端/服务器库
  • ZeroMQ:高速,模块化的异步通信库

物理学

动力学仿真引擎

  • Box2D:2D的游戏物理引擎。
  • Bullet:3D的游戏物理引擎。
  • Chipmunk:快速,轻量级的2D游戏物理库
  • LiquidFun:2D的游戏物理引擎
  • ODE:开放动力学引擎-开源,高性能库,模拟刚体动力学。
  • ofxBox2d:Box2D开源框架包装器。
  • Simbody:高性能C++多体动力学/物理库,模拟关节生物力学和机械系统,像车辆,机器人和人体骨骼。

机器人学

  • MOOS-IvP:一组开源C++模块,提供机器人平台的自主权,尤其是自主的海洋车辆。
  • MRPT:移动机器人编程工具包
  • PCL:点云库是一个独立的,大规模的开放项目,用于2D/3D图像和点云处理。
  • Robotics Library (RL): 一个独立的C++库,包括机器人动力学,运动规划和控制。
  • RobWork:一组C++库的集合,用于机器人系统的仿真和控制。
  • ROS:机器人操作系统,提供了一些库和工具帮助软件开发人员创建机器人应用程序。

科学计算

  • FFTW:用一维或者多维计算DFT的C语言库。
  • GSL:GNU科学库。

脚本

  • ChaiScript:用于C++的易于使用的嵌入式脚本语言。
  • Lua:用于配置文件和基本应用程序脚本的小型快速脚本引擎。
  • luacxx:用于创建Lua绑定的C++ 11 API
  • SWIG:一个可以让你的C++代码链接到JavaScript,Perl,PHP,Python,Tcl和Ruby的包装器/接口生成器
  • V7:嵌入式的JavaScript 引擎。
  • V8:谷歌的快速JavaScript引擎,可以被嵌入到任何C++应用程序中。

序列化

  • Cap’n Proto:快速数据交换格式和RPC系统。
  • cereal:C++11 序列化库
  • FlatBuffers:内存高效的序列化库
  • MessagePack:C/C++的高效二进制序列化库,例如 JSON
  • protobuf:协议缓冲,谷歌的数据交换格式。
  • protobuf-c:C语言的协议缓冲实现
  • SimpleBinaryEncoding:用于低延迟应用程序的对二进制格式的应用程序信息的编码和解码。
  • Thrift:高效的跨语言IPC/RPC,用于C++,Java,Python,PHP,C#和其它多种语言中,最初由Twitter开发。<span style="color: #ff0000;">注:原文有误,应该是 facebook 在2007年开发的,现在是 Apache 在维护</span>

视频

  • libvpx:VP8/VP9编码解码SDK
  • FFmpeg:一个完整的,跨平台的解决方案,用于记录,转换视频和音频流。
  • libde265:开放的h.265视频编解码器的实现。
  • OpenH264:开源H.364 编解码器。
  • Theora:免费开源的视频压缩格式。

虚拟机

  • CarpVM:C中有趣的VM,让我们一起来看看这个。
  • MicroPython:旨在实现单片机上Python3.x的实现
  • TinyVM:用纯粹的ANSI C编写的小型,快速,轻量级的虚拟机。

Web应用框架

  • Civetweb:提供易于使用,强大的,C/C++嵌入式Web服务器,带有可选的CGI,SSL和Lua支持。
  • CppCMS:免费高性能的Web开发框架(不是 CMS).
  • Crow:一个C++微型web框架(灵感来自于Python Flask)
  • Kore:使用C语言开发的用于web应用程序的超快速和灵活的web服务器/框架。
  • libOnion:轻量级的库,帮助你使用C编程语言创建web服务器。
  • QDjango:使用C++编写的,基于Qt库的web框架,试图效仿Django API,因此得此名。
  • Wt:开发Web应用的C++库。

XML

XML就是个垃圾,xml的解析很烦人,对于计算机它也是个灾难。这种糟糕的东西完全没有存在的理由了。-Linus Torvalds

  • Expat:用C语言编写的xml解析库
  • Libxml2:Gnome的xml C解析器和工具包
  • libxml++:C++的xml解析器
  • PugiXML:用于C++的,支持XPath的轻量级,简单快速的XML解析器。
  • RapidXml:试图创建最快速的XML解析器,同时保持易用性,可移植性和合理的W3C兼容性。
  • TinyXML:简单小型的C++XML解析器,可以很容易地集成到其它项目中。
  • TinyXML2:简单快速的C++CML解析器,可以很容易集成到其它项目中。
  • TinyXML++:TinyXML的一个全新的接口,使用了C++的许多许多优势,模板,异常和更好的异常处理。
  • Xerces-C++:用可移植的C++的子集编写的XML验证解析器。

多项混杂

一些有用的库或者工具,但是不适合上面的分类,或者还没有分类。

  • C++ Format:C++的小型,安全和快速格式化库
  • casacore:从aips++ 派生的一系列C++核心库
  • cxx-prettyprint:用于C++容器的打印库
  • DynaPDF:易于使用的PDF生成库
  • gcc-poison:帮助开发人员禁止应用程序中的不安全的C/C++函数的简单的头文件。
  • googlemock:编写和使用C++模拟类的库
  • HTTP Parser:C的http请求/响应解析器
  • libcpuid:用于x86 CPU检测盒特征提取的小型C库
  • libevil:许可证管理器
  • libusb:允许移动访问USB设备的通用USB库
  • PCRE:正则表达式C库,灵感来自于Perl中正则表达式的功能。
  • Remote Call Framework:C++的进程间通信框架。
  • Scintilla:开源的代码编辑控件
  • Serial Communication Library:C++语言编写的跨平台,串口库。
  • SDS:C的简单动态字符串库
  • SLDR:超轻的DNS解析器
  • SLRE: 超轻的正则表达式库
  • Stage:移动机器人模拟器
  • VarTypes:C++/Qt4功能丰富,面向对象的管理变量的框架。
  • ZBar:‘条形码扫描器’库,可以扫描照片,图片和视频流中的条形码,并返回结果。
  • CppVerbalExpressions:易于使用的C++正则表达式
  • QtVerbalExpressions:基于C++ VerbalExpressions 库的Qt库
  • PHP-CPP:使用C++来构建PHP扩展的库
  • Better String:C的另一个字符串库,功能更丰富,但是没有缓冲溢出问题,还包含了一个C++包装器。

软件

用于创建开发环境的软件

编译器

C/C++编译器列表

在线编译器

在线C/C++编译器列表

  • codepad:在线编译器/解释器,一个简单的协作工具
  • CodeTwist:一个简单的在线编译器/解释器,你可以粘贴的C,C++或者Java代码,在线执行并查看结果
  • coliru:在线编译器/shell, 支持各种C++编译器
  • Compiler Explorer:交互式编译器,可以进行汇编输出
  • CompileOnline:Linux上在线编译和执行C++程序
  • Ideone:一个在线编译器和调试工具,允许你在线编译源代码并执行,支持60多种编程语言。

调试器

C/C++调试器列表

集成开发环境(IDE)

C/C++集成开发环境列表

  • AppCode:构建与JetBrains’ IntelliJ IDEA 平台上的用于Objective-C,C,C++,Java和Java开发的集成开发环境
  • CLion:来自JetBrains的跨平台的C/C++的集成开发环境
  • Code::Blocks:免费C,C++和Fortran的集成开发环境
  • CodeLite:另一个跨平台的免费的C/C++集成开发环境
  • Dev-C++:可移植的C/C++/C++11集成开发环境
  • Eclipse CDT:基于Eclipse平台的功能齐全的C和C++集成开发环境
  • Geany:轻量级的快速,跨平台的集成开发环境。
  • IBM VisualAge:来自IBM的家庭计算机集成开发环境。
  • Irony-mode:由libclang驱动的用于Emacs的C/C++微模式
  • KDevelop:免费开源集成开发环境
  • Microsoft Visual Studio:来自微软的集成开发环境
  • NetBeans:主要用于Java开发的的集成开发环境,也支持其他语言,尤其是PHP,C/C++和HTML5。
  • Qt Creator:跨平台的C++,Javascript和QML集成开发环境,也是Qt SDK的一部分。
  • rtags:C/C++的客户端服务器索引,用于 跟基于clang的emacs的集成
  • Xcode:由苹果公司开发
  • YouCompleteMe:一个用于Vim的根据你敲的代码快速模糊搜索并进行代码补全的引擎。

构建系统

  • Bear:用于为clang工具生成编译数据库的工具
  • Biicode:基于文件的简单依赖管理器。
  • CMake:跨平台的免费开源软件用于管理软件使用独立编译的方法进行构建的过程。
  • CPM:基于CMake和Git的C++包管理器
  • FASTBuild:高性能,开源的构建系统,支持高度可扩展性的编译,缓冲和网络分布。
  • Ninja:专注于速度的小型构建系统
  • Scons:使用Python scipt 配置的软件构建工具
  • tundra:高性能的代码构建系统,甚至对于非常大型的软件项目,也能提供最好的增量构建次数。
  • tup:基于文件的构建系统,用于后台监控变化的文件。

静态代码分析

提高质量,减少瑕疵的代码分析工具列表

查看原文

Dlyw 赞了文章 · 10月9日

C++ 常用库

标准库

C++标准库,包括了STL容器,算法和函数等。

框架

C++通用框架和库

  • Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合
  • ASL:Adobe源代码库提供了同行的评审和可移植的C++源代码库。
  • Boost:大量通用C++库的集合。
  • BDE:来自于彭博资讯实验室的开发环境。
  • Cinder:提供专业品质创造性编码的开源开发社区。
  • Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。
  • Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。
  • EASTL:EA-STL公共部分
  • ffead-cpp:企业应用程序开发框架
  • Folly:由Facebook开发和使用的开源C++库
  • JUCE:包罗万象的C++类库,用于开发跨平台软件
  • libPhenom:用于构建高性能和高度可扩展性系统的事件框架。
  • LibSourcey:用于实时的视频流和高性能网络应用程序的C++11 evented IO
  • LibU: C语言写的多平台工具库
  • Loki:C++库的设计,包括常见的设计模式和习语的实现。
  • MiLi:只含头文件的小型C++库
  • openFrameworks:开发C++工具包,用于创意性编码。
  • Qt:跨平台的应用程序和用户界面框架
  • Reason:跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。
  • ROOT:具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。
  • STLport:是STL具有代表性的版本
  • STXXL:用于额外的大型数据集的标准模板库。
  • Ultimate++:C++跨平台快速应用程序开发框架
  • Windows Template Library:用于开发Windows应用程序和UI组件的C++库
  • Yomm11:C++11的开放multi-methods.

人工智能

  • btsk:游戏行为树启动器工具
  • Evolving Objects:基于模板的,ANSI C++演化计算库,能够帮助你非常快速地编写出自己的随机优化算法。
  • Neu:C++11框架,编程语言集,用于创建人工智能应用程序的多用途软件系统。

异步事件循环

  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库。
  • libev:功能齐全,高性能的时间循环,轻微地仿效libevent,但是不再像libevent一样有局限性,也修复了它的一些bug。
  • libevent:事件通知库
  • libuv:跨平台异步I/O。

音频

音频,声音,音乐,数字化音乐库

  • FMOD:易于使用的跨平台的音频引擎和音频内容的游戏创作工具。
  • Maximilian:C++音频和音乐数字信号处理库
  • OpenAL:开源音频库—跨平台的音频API
  • Opus:一个完全开放的,免版税的,高度通用的音频编解码器
  • Speex:免费编解码器,为Opus所废弃
  • Tonic: C++易用和高效的音频合成
  • Vorbis: Ogg Vorbis是一种完全开放的,非专有的,免版税的通用压缩音频格式。

生态学

生物信息,基因组学和生物技术

  • libsequence:用于表示和分析群体遗传学数据的C++库。
  • SeqAn:专注于生物数据序列分析的算法和数据结构。
  • Vcflib:用于解析和处理VCF文件的C++库
  • Wham:直接把联想测试应用到BAM文件的基因结构变异。

压缩

压缩和归档库

  • bzip2:一个完全免费,免费专利和高质量的数据压缩
  • doboz:能够快速解压缩的压缩库
  • PhysicsFS:对各种归档提供抽象访问的库,主要用于视频游戏,设计灵感部分来自于Quake3的文件子系统。
  • KArchive:用于创建,读写和操作文件档案(例如zip和 tar)的库,它通过QIODevice的一系列子类,使用gzip格式,提供了透明的压缩和解压缩的数据。
  • LZ4:非常快速的压缩算法
  • LZHAM:无损压缩数据库,压缩比率跟LZMA接近,但是解压缩速度却要快得多。
  • LZMA:7z格式默认和通用的压缩方法。
  • LZMAT:及其快速的实时无损数据压缩库
  • miniz:单一的C源文件,紧缩/膨胀压缩库,使用zlib兼容API,ZIP归档读写,PNG写方式。
  • Minizip:Zlib最新bug修复,支持PKWARE磁盘跨越,AES加密和IO缓冲。
  • Snappy:快速压缩和解压缩
  • ZLib:非常紧凑的数据流压缩库
  • ZZIPlib:提供ZIP归档的读权限。

并发性

并发执行和多线程

  • Boost.Compute:用于OpenCL的C++GPU计算库
  • Bolt:针对GPU进行优化的C++模板库
  • C++React:用于C++11的反应性编程库
  • Intel TBB:Intel线程构件块
  • Libclsph:基于OpenCL的GPU加速SPH流体仿真库
  • OpenCL:并行编程的异构系统的开放标准
  • OpenMP:OpenMP API
  • Thrust:类似于C++标准模板库的并行算法库
  • HPX:用于任何规模的并行和分布式应用程序的通用C++运行时系统
  • VexCL:用于OpenCL/CUDA 的C++向量表达式模板库。

容器

  • C++ B-tree:基于B树数据结构,实现命令内存容器的模板库
  • Hashmaps: C++中开放寻址哈希表算法的实现

密码学

  • Bcrypt:一个跨平台的文件加密工具,加密文件可以移植到所有可支持的操作系统和处理器中。
  • BeeCrypt
  • Botan: C++加密库
  • Crypto++:一个有关加密方案的免费的C++库
  • GnuPG: OpenPGP标准的完整实现
  • GnuTLS:实现了SSL,TLS和DTLS协议的安全通信库
  • Libgcrypt
  • libmcrypt
  • LibreSSL:免费的SSL/TLS协议,属于2014 OpenSSL的一个分支
  • LibTomCrypt:一个非常全面的,模块化的,可移植的加密工具
  • libsodium:基于NaCI的加密库,固执己见,容易使用
  • Nettle底层的加密库
  • OpenSSL: 一个强大的,商用的,功能齐全的,开放源代码的加密库。
  • Tiny AES128 in C:用C实现的一个小巧,可移植的实现了AES128ESB的加密算法

数据库

数据库,SQL服务器,ODBC驱动程序和工具

  • hiberlite:用于Sqlite3的C++对象关系映射
  • Hiredis: 用于Redis数据库的很简单的C客户端库
  • LevelDB: 快速键值存储库
  • LMDB:符合数据库四大基本元素的嵌入键值存储
  • MySQL++:封装了MySql的C API的C++ 包装器
  • RocksDB:来自Facebook的嵌入键值的快速存储
  • SQLite:一个完全嵌入式的,功能齐全的关系数据库,只有几百KB,可以正确包含到你的项目中。

调试

调试库, 内存和资源泄露检测,单元测试

  • Boost.Test:Boost测试库
  • Catch:一个很时尚的,C++原生的框架,只包含头文件,用于单元测试,测试驱动开发和行为驱动开发。
  • CppUnit:由JUnit移植过来的C++测试框架
  • CTest:CMake测试驱动程序
  • googletest:谷歌C++测试框架
  • ig-debugheap:用于跟踪内存错误的多平台调试堆
  • libtap:用C语言编写测试
  • MemTrack—用于C++跟踪内存分配
  • microprofile- 跨平台的网络试图分析器
  • minUnit:使用C写的迷你单元测试框架,只使用了两个宏
  • Remotery:用于web视图的单一C文件分析器
  • UnitTest++:轻量级的C++单元测试框架

游戏引擎

  • Cocos2d-x:一个跨平台框架,用于构建2D游戏,互动图书,演示和其他图形应用程序。
  • Grit:社区项目,用于构建一个免费的游戏引擎,实现开放的世界3D游戏。
  • Irrlicht:C++语言编写的开源高性能的实时#D引擎
  • Polycode:C++实现的用于创建游戏的开源框架(与Lua绑定)。

图形用户界面

  • CEGUI: 很灵活的跨平台GUI库
  • FLTK:快速,轻量级的跨平台的C++GUI工具包。
  • GTK+: 用于创建图形用户界面的跨平台工具包
  • gtkmm:用于受欢迎的GUI库GTK+的官方C++接口。
  • imgui:拥有最小依赖关系的立即模式图形用户界面
  • libRocketlibRocket是一个C++ HTML/CSS 游戏接口中间件
  • MyGUI:快速,灵活,简单的GUI
  • Ncurses:终端用户界面
  • QCustomPlot:没有更多依赖关系的Qt绘图控件
  • Qwt:用户与技术应用的Qt 控件
  • QwtPlot3D:功能丰富的基于Qt/OpenGL的C++编程库,本质上提供了一群3D控件
  • OtterUIOtterUI是用于嵌入式系统和互动娱乐软件的用户界面开发解决方案
  • PDCurses包含源代码和预编译库的公共图形函数库
  • wxWidgetsC++库,允许开发人员使用一个代码库可以为widows, Mac OS X,Linux和其他平台创建应用程序

图形

  • bgfx:跨平台的渲染库
  • Cairo:支持多种输出设备的2D图形库
  • Horde3D一个小型的3D渲染和动画引擎
  • magnumC++11和OpenGL 2D/3D 图形引擎
  • Ogre 3D用C++编写的一个面向场景,实时,灵活的3D渲染引擎(并非游戏引擎)
  • OpenSceneGraph具有高性能的开源3D图形工具包
  • Panda3D用于3D渲染和游戏开发的框架,用Python和C++编写。
  • Skia用于绘制文字,图形和图像的完整的2D图形库
  • urho3d跨平台的渲染和游戏引擎。

图像处理

  • Boost.GIL:通用图像库
  • CImg:用于图像处理的小型开源C++工具包
  • CxImage:用于加载,保存,显示和转换的图像处理和转换库,可以处理的图片格式包括 BMP, JPEG, GIF, PNG, TIFF, MNG, ICO, PCX, TGA, WMF, WBMP, JBG, J2K。
  • FreeImage:开源库,支持现在多媒体应用所需的通用图片格式和其他格式。
  • GDCM:Grassroots DICOM 库
  • ITK:跨平台的开源图像分析系统
  • Magick++:ImageMagick程序的C++接口
  • MagickWnd:ImageMagick程序的C++接口
  • OpenCV: 开源计算机视觉类库
  • tesseract-ocr:OCR引擎
  • VIGRA:用于图像分析通用C++计算机视觉库
  • VTK:用于3D计算机图形学,图像处理和可视化的开源免费软件系统。

国际化

  • gettext:GNU `gettext’
  • IBM ICU:提供Unicode 和全球化支持的C、C++ 和Java库
  • libiconv:用于不同字符编码之间的编码转换库

Jason

  • frozen: C/C++的Jason解析生成器
  • Jansson:进行编解码和处理Jason数据的C语言库
  • jbson:C++14中构建和迭代BSON data,和Json 文档的库
  • JeayeSON:非常健全的C++ JSON库,只包含头文件
  • JSON++: C++ JSON 解析器
  • json-parser:用可移植的ANSI C编写的JSON解析器,占用内存非常少
  • json11:一个迷你的C++11 JSON库
  • jute:非常简单的C++ JSON解析器
  • ibjson:C语言中的JSON解析和打印库,很容易和任何模型集成。
  • libjson:轻量级的JSON库
  • PicoJSON:C++中JSON解析序列化,只包含头文件
  • qt-json:用于JSON数据和 QVariant层次间的相互解析的简单类
  • QJson:将JSON数据映射到QVariant对象的基于Qt的库
  • RapidJSON: 用于C++的快速JSON 解析生成器,包含SAX和DOM两种风格的API
  • YAJL:C语言中快速流JSON解析库

日志

  • Boost.Log:设计非常模块化,并且具有扩展性
  • easyloggingpp:C++日志库,只包含单一的头文件。
  • Log4cpp:一系列C++类库,灵活添加日志到文件,系统日志,IDSA和其他地方。
  • templog:轻量级C++库,可以添加日志到你的C++应用程序中

机器学习

  • Caffe:快速的神经网络框架
  • CCV:以C语言为核心的现代计算机视觉库
  • mlpack:可扩展的C++机器学习库
  • OpenCV:开源计算机视觉库
  • Recommender:使用协同过滤进行产品推荐/建议的C语言库。
  • SHOGUN:Shogun 机器学习工具
  • sofia-ml:用于机器学习的快速增量算法套件

数学

  • Armadillo:高质量的C++线性代数库,速度和易用性做到了很好的平衡。语法和MatlAB很相似
  • blaze:高性能的C++数学库,用于密集和稀疏算法。
  • ceres-solver:来自谷歌的C++库,用于建模和解决大型复杂非线性最小平方问题。
  • CGal: 高效,可靠的集合算法集合
  • cml:用于游戏和图形的免费C++数学库
  • Eigen:高级C++模板头文件库,包括线性代数,矩阵,向量操作,数值解决和其他相关的算法。
  • GMTL:数学图形模板库是一组广泛实现基本图形的工具。
  • GMP:用于个高精度计算的C/C++库,处理有符号整数,有理数和浮点数。

多媒体

  • GStreamer:构建媒体处理组件图形的库
  • LIVE555 Streaming Media:使用开放标准协议(RTP/RTCP, RTSP, SIP) 的多媒体流库
  • libVLC:libVLC (VLC SDK)媒体框架
  • QtAv:基于Qt和FFmpeg的多媒体播放框架,能够帮助你轻而易举地编写出一个播放器
  • SDL:简单直控媒体层
  • SFML:快速,简单的多媒体库

网络

  • ACE:C++面向对象网络变成工具包
  • Boost.Asio:用于网络和底层I/O编程的跨平台的C++库
  • Casablanca:C++ REST SDK
  • cpp-netlib:高级网络编程的开源库集合
  • Dyad.c:C语言的异步网络
  • libcurl:多协议文件传输库
  • Mongoose<span style="text-decoration: underline;">:</span>非常轻量级的网络服务器
  • Muduo:用于Linux多线程服务器的C++非阻塞网络库
  • net_skeleton:C/C++的TCP 客户端/服务器库
  • nope.c:基于C语言的超轻型软件平台,用于可扩展的服务器端和网络应用。 对于C编程人员,可以考虑node.js
  • Onion:C语言HTTP服务器库,其设计为轻量级,易使用。
  • POCO:用于构建网络和基于互联网应用程序的C++类库,可以运行在桌面,服务器,移动和嵌入式系统。
  • RakNet:为游戏开发人员提供的跨平台的开源C++网络引擎。
  • Tuf o:用于Qt之上的C++构建的异步Web框架。
  • WebSocket++:基于C++/Boost Aiso的websocket 客户端/服务器库
  • ZeroMQ:高速,模块化的异步通信库

物理学

动力学仿真引擎

  • Box2D:2D的游戏物理引擎。
  • Bullet:3D的游戏物理引擎。
  • Chipmunk:快速,轻量级的2D游戏物理库
  • LiquidFun:2D的游戏物理引擎
  • ODE:开放动力学引擎-开源,高性能库,模拟刚体动力学。
  • ofxBox2d:Box2D开源框架包装器。
  • Simbody:高性能C++多体动力学/物理库,模拟关节生物力学和机械系统,像车辆,机器人和人体骨骼。

机器人学

  • MOOS-IvP:一组开源C++模块,提供机器人平台的自主权,尤其是自主的海洋车辆。
  • MRPT:移动机器人编程工具包
  • PCL:点云库是一个独立的,大规模的开放项目,用于2D/3D图像和点云处理。
  • Robotics Library (RL): 一个独立的C++库,包括机器人动力学,运动规划和控制。
  • RobWork:一组C++库的集合,用于机器人系统的仿真和控制。
  • ROS:机器人操作系统,提供了一些库和工具帮助软件开发人员创建机器人应用程序。

科学计算

  • FFTW:用一维或者多维计算DFT的C语言库。
  • GSL:GNU科学库。

脚本

  • ChaiScript:用于C++的易于使用的嵌入式脚本语言。
  • Lua:用于配置文件和基本应用程序脚本的小型快速脚本引擎。
  • luacxx:用于创建Lua绑定的C++ 11 API
  • SWIG:一个可以让你的C++代码链接到JavaScript,Perl,PHP,Python,Tcl和Ruby的包装器/接口生成器
  • V7:嵌入式的JavaScript 引擎。
  • V8:谷歌的快速JavaScript引擎,可以被嵌入到任何C++应用程序中。

序列化

  • Cap’n Proto:快速数据交换格式和RPC系统。
  • cereal:C++11 序列化库
  • FlatBuffers:内存高效的序列化库
  • MessagePack:C/C++的高效二进制序列化库,例如 JSON
  • protobuf:协议缓冲,谷歌的数据交换格式。
  • protobuf-c:C语言的协议缓冲实现
  • SimpleBinaryEncoding:用于低延迟应用程序的对二进制格式的应用程序信息的编码和解码。
  • Thrift:高效的跨语言IPC/RPC,用于C++,Java,Python,PHP,C#和其它多种语言中,最初由Twitter开发。<span style="color: #ff0000;">注:原文有误,应该是 facebook 在2007年开发的,现在是 Apache 在维护</span>

视频

  • libvpx:VP8/VP9编码解码SDK
  • FFmpeg:一个完整的,跨平台的解决方案,用于记录,转换视频和音频流。
  • libde265:开放的h.265视频编解码器的实现。
  • OpenH264:开源H.364 编解码器。
  • Theora:免费开源的视频压缩格式。

虚拟机

  • CarpVM:C中有趣的VM,让我们一起来看看这个。
  • MicroPython:旨在实现单片机上Python3.x的实现
  • TinyVM:用纯粹的ANSI C编写的小型,快速,轻量级的虚拟机。

Web应用框架

  • Civetweb:提供易于使用,强大的,C/C++嵌入式Web服务器,带有可选的CGI,SSL和Lua支持。
  • CppCMS:免费高性能的Web开发框架(不是 CMS).
  • Crow:一个C++微型web框架(灵感来自于Python Flask)
  • Kore:使用C语言开发的用于web应用程序的超快速和灵活的web服务器/框架。
  • libOnion:轻量级的库,帮助你使用C编程语言创建web服务器。
  • QDjango:使用C++编写的,基于Qt库的web框架,试图效仿Django API,因此得此名。
  • Wt:开发Web应用的C++库。

XML

XML就是个垃圾,xml的解析很烦人,对于计算机它也是个灾难。这种糟糕的东西完全没有存在的理由了。-Linus Torvalds

  • Expat:用C语言编写的xml解析库
  • Libxml2:Gnome的xml C解析器和工具包
  • libxml++:C++的xml解析器
  • PugiXML:用于C++的,支持XPath的轻量级,简单快速的XML解析器。
  • RapidXml:试图创建最快速的XML解析器,同时保持易用性,可移植性和合理的W3C兼容性。
  • TinyXML:简单小型的C++XML解析器,可以很容易地集成到其它项目中。
  • TinyXML2:简单快速的C++CML解析器,可以很容易集成到其它项目中。
  • TinyXML++:TinyXML的一个全新的接口,使用了C++的许多许多优势,模板,异常和更好的异常处理。
  • Xerces-C++:用可移植的C++的子集编写的XML验证解析器。

多项混杂

一些有用的库或者工具,但是不适合上面的分类,或者还没有分类。

  • C++ Format:C++的小型,安全和快速格式化库
  • casacore:从aips++ 派生的一系列C++核心库
  • cxx-prettyprint:用于C++容器的打印库
  • DynaPDF:易于使用的PDF生成库
  • gcc-poison:帮助开发人员禁止应用程序中的不安全的C/C++函数的简单的头文件。
  • googlemock:编写和使用C++模拟类的库
  • HTTP Parser:C的http请求/响应解析器
  • libcpuid:用于x86 CPU检测盒特征提取的小型C库
  • libevil:许可证管理器
  • libusb:允许移动访问USB设备的通用USB库
  • PCRE:正则表达式C库,灵感来自于Perl中正则表达式的功能。
  • Remote Call Framework:C++的进程间通信框架。
  • Scintilla:开源的代码编辑控件
  • Serial Communication Library:C++语言编写的跨平台,串口库。
  • SDS:C的简单动态字符串库
  • SLDR:超轻的DNS解析器
  • SLRE: 超轻的正则表达式库
  • Stage:移动机器人模拟器
  • VarTypes:C++/Qt4功能丰富,面向对象的管理变量的框架。
  • ZBar:‘条形码扫描器’库,可以扫描照片,图片和视频流中的条形码,并返回结果。
  • CppVerbalExpressions:易于使用的C++正则表达式
  • QtVerbalExpressions:基于C++ VerbalExpressions 库的Qt库
  • PHP-CPP:使用C++来构建PHP扩展的库
  • Better String:C的另一个字符串库,功能更丰富,但是没有缓冲溢出问题,还包含了一个C++包装器。

软件

用于创建开发环境的软件

编译器

C/C++编译器列表

在线编译器

在线C/C++编译器列表

  • codepad:在线编译器/解释器,一个简单的协作工具
  • CodeTwist:一个简单的在线编译器/解释器,你可以粘贴的C,C++或者Java代码,在线执行并查看结果
  • coliru:在线编译器/shell, 支持各种C++编译器
  • Compiler Explorer:交互式编译器,可以进行汇编输出
  • CompileOnline:Linux上在线编译和执行C++程序
  • Ideone:一个在线编译器和调试工具,允许你在线编译源代码并执行,支持60多种编程语言。

调试器

C/C++调试器列表

集成开发环境(IDE)

C/C++集成开发环境列表

  • AppCode:构建与JetBrains’ IntelliJ IDEA 平台上的用于Objective-C,C,C++,Java和Java开发的集成开发环境
  • CLion:来自JetBrains的跨平台的C/C++的集成开发环境
  • Code::Blocks:免费C,C++和Fortran的集成开发环境
  • CodeLite:另一个跨平台的免费的C/C++集成开发环境
  • Dev-C++:可移植的C/C++/C++11集成开发环境
  • Eclipse CDT:基于Eclipse平台的功能齐全的C和C++集成开发环境
  • Geany:轻量级的快速,跨平台的集成开发环境。
  • IBM VisualAge:来自IBM的家庭计算机集成开发环境。
  • Irony-mode:由libclang驱动的用于Emacs的C/C++微模式
  • KDevelop:免费开源集成开发环境
  • Microsoft Visual Studio:来自微软的集成开发环境
  • NetBeans:主要用于Java开发的的集成开发环境,也支持其他语言,尤其是PHP,C/C++和HTML5。
  • Qt Creator:跨平台的C++,Javascript和QML集成开发环境,也是Qt SDK的一部分。
  • rtags:C/C++的客户端服务器索引,用于 跟基于clang的emacs的集成
  • Xcode:由苹果公司开发
  • YouCompleteMe:一个用于Vim的根据你敲的代码快速模糊搜索并进行代码补全的引擎。

构建系统

  • Bear:用于为clang工具生成编译数据库的工具
  • Biicode:基于文件的简单依赖管理器。
  • CMake:跨平台的免费开源软件用于管理软件使用独立编译的方法进行构建的过程。
  • CPM:基于CMake和Git的C++包管理器
  • FASTBuild:高性能,开源的构建系统,支持高度可扩展性的编译,缓冲和网络分布。
  • Ninja:专注于速度的小型构建系统
  • Scons:使用Python scipt 配置的软件构建工具
  • tundra:高性能的代码构建系统,甚至对于非常大型的软件项目,也能提供最好的增量构建次数。
  • tup:基于文件的构建系统,用于后台监控变化的文件。

静态代码分析

提高质量,减少瑕疵的代码分析工具列表

查看原文

赞 22 收藏 32 评论 0

Dlyw 关注了用户 · 9月29日

公子 @lizheming

  • 额米那个陀佛,无量那个天尊!
  • SF啥时候出注销功能啊

关注 3970

Dlyw 赞了文章 · 8月11日

使用Node.js实现一个express框架

手写一个express系列

express的基本用法

const express = require("express");
const app = express();

app.get("/test", (req, res, next) => {
  console.log("*1");
//   res.end("2");
  next();
});

app.get("/test", (req, res, next) => {
  console.log("*2");
  res.end("2");
});

app.listen(8888, (err) => {
  !err && console.log("监听成功");
});
  • 当我访问localhost:8888/test时候,返回了:2,服务端打印了
*1
*2
  • 从上面可以看到什么?

    • express默认引入调用后返回一个app对象
    • app.listen 会启动进程监听端口
    • 每次收到请求,对应的urlmethod会触发相应挂载在app上对应的回调函数
    • 调用 next 方法,会触发下一个

一起来实现一个简单的express框架

  • 定义属于我们的express文件入口,这里使用class来实现
class express {

}

module.exports = express;
  • 需要的原生模块http,创建进程监听端口
const { createServer } = require("http");
  • 给 class 定义 listen 方法,监听端口
class express {
  listen(...args) {
    createServer(cb).listen(...args);
  }
}
  • 这样就可以通过调用 classlisten 去调用 http 模块的 listen 了,这里的cb我们可以先不管,你要知道每次接受到请求,必然会调用 cb 函数,这个是 createServer 原生模块帮我们封装好的

实现接收到请求触发

  • 实现app.get app.post等方法

    • 目前我们接受到响应,就会触发 cb 这个回调函数,那我们打印下,看看是什么参数?
class express {
  cb() {
    return (req, res) => {
      console.log(res, res, "开始行动");
    };
  }
  listen(...args) {
    createServer(this.cb()).listen(...args);
  }
}
  • 发现此时的 reqres 正是我们想要的可读流和可写流.

  • 开始编写 getpost 方法

    • 这里注意,有路由是'/'的,这种是不管任何路由都会触发一次
  constructor() {
    this.routers = {
      get: [],
      post: [],
    };
  }

  get(path, handle) {
    this.routers.get.push({
      path,
      handle,
    });
  }
  post(path, handle) {
    this.routers.post.push({
      path,
      handle,
    });
  }
  • 初始化时候定义 get、post 的数组储存对应的 pathhandle.
  • 需要触发路由回调的时候,首先要找到对应的请求方式下对应的 urlhandle 方法,然后触发回调.
  • 如何找到对应请求方式下的 url 对应的 handle 方法? 在接到请求时候就要遍历一次

    • 这里要考虑匹配多个路由,意味着,我们可能遇到像最开始一样,有两个 get 方式的 test 路由
  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      console.log(this.routers[method], ",method");
      const url = req.url;
      this.routers[method].forEach((item) => {
        item.path === url && item.handle(req, res);
      });
    };
  }
  listen(...args) {
    createServer(this.cb()).listen(...args);
  }
  • 上面根据 method 找到对应的数组,遍历找到请求的路由,触发回调,此时已经能正常返回数据了
[ { method: 'get', path: '/test', handle: [Function] } ] ,method
  • 此时最简单的express已经完成了,但是我们好像忘了最重要的中间件

完成最重要的中间件功能

  • 首先要知道,express中间件分两种,一种带路由的,那就是根据路由决定是否触发
  • 另外一种就是不带路由的,像静态资源这种. 是用户访问任何路由都要触发一次的
  • 那我们需要一个 all 数组储存这种任意路由都需要匹配触发的
 constructor() {
    this.routers = {
      get: [],
      post: [],
      all: [],
    };
  }
  • 之前的直接通过 push 方式是太粗暴.如果用户需要中间件功能,不传路由,那就要做特殊处理,这里通过一个中间函数处理下
  • 改造getpost方法,定义handleAddRouter方法
  handleAddRouter(path, handle) {
    let router = {};
    if (typeof path === "string") {
      router = {
        path,
        handle,
      };
    } else {
      router = {
        path: "/",
        handle: path,
      };
    }
    return router;
  }

  get(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.get.push(router);
  }

  post(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.post.push(router);
  }

  use(path, handle) {
    const router = this.handleAddRouter(path, handle);
    this.routers.all.push(router);
  }

  • 每次添加之前,先触发一次handleAddRouter,如果是 path 为空的中间件,直接传入函数的,那么 path 帮它设置成'/'
  • 我们还遗留了一个点,next的实现,因为我们现在加了all这个数组后,意味着可能有多个中间件,那么可能一次请求打过来,就要触发多个路由
这里要注意,promise.then 源码实现和 express 的 next、以及 koa 的洋葱圈、redux 的中间件实现,有着一丁点相似,当你能真的领悟前后端框架源码时候,发现大都相似
  • 阅读我的文章,足以击破所有前后端源码.而且可以手写出来, 我们只学最核心的,抓重点学习,野蛮生长!

实现next

  • 思路:

    • 首先要找到所有匹配的路由
    • 然后逐个执行(看 next 的调用)
  • 定义search方法,找到所有匹配的路由
  search(method, url) {
    const matchedList = [];
    [...this.routers[method], ...this.routers.all].forEach((item) => {
      item.path === url && matchedList.push(item.handle);
    });
    return matchedList;
  }

  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      const url = req.url;
      const matchedList = this.search(method, url);
    };
  }
  • matchedList就是我们想要找到的所有路由
  • 为了完成next,我们要将req ,res , matchedList存入闭包中,定义handle方法
  handle(req, res, matchedList) {
    const next = () => {
      const midlleware = matchedList.shift();
      if (midlleware) {
        midlleware(req, res, next);
      }
    };
    next();
  }
  cb() {
    return (req, res) => {
      const method = req.method.toLowerCase();
      const url = req.url;
      const matchedList = this.search(method, url);
      this.handle(req, res, matchedList);
    };
  }

  • 这样我们就完成了next方法,只要手动调用 next 就会调用下一个匹配到的路由回调函数

  • 不到一百行代码,就完成了这个简单的express框架

写在最后

  • 只要你根据我这些文章去认真自己实现一次,一年内拿个 P6 应该没什么问题
  • 大道至简,希望你能通过这些文章真的学到框架的原理,进而自己能写出一些框架,走向更高的层级
  • 我是Peter,曾经 20 万人超级群桌面软件的架构师,现在就职于明源云,担任分公司前端负责人,目前深圳这边需要招聘两位中高级前端,3D数据可视化方向,期待你的到来
  • 如果感觉本文对你有帮助,别忘了点个在看关注. 我们的技术团队也会不断产出原创文章, 一起见证各位的成长
查看原文

赞 17 收藏 9 评论 0

Dlyw 收藏了文章 · 2019-12-02

webpack模块化原理-commonjs

我们都知道,webpack作为一个构建工具,解决了前端代码缺少模块化能力的问题。我们写的代码,经过webpack构建和包装之后,能够在浏览器以模块化的方式运行。这些能力,都是因为webpack对我们的代码进行了一层包装,本文就以webpack生成的代码入手,分析webpack是如何实现模块化的。

PS: webpack的模块不仅指js,包括css、图片等资源都可以以模块看待,但本文只关注js。

准备

首先我们创建一个简单入口模块index.js和一个依赖模块bar.js:

//index.js
'use strict';
var bar = require('./bar');
function foo() {
    return bar.bar();
}
//bar.js
'use strict';
exports.bar = function () {
    return 1;
}

webpack配置如下:

var path = require("path");
module.exports = {
    entry: path.join(__dirname, 'index.js'),
    output: {
        path: path.join(__dirname, 'outs'),
        filename: 'index.js'
    },
};

这是一个最简单的配置,只指定了模块入口和输出路径,但已经满足了我们的要求。

在根目录下执行webpack,得到经过webpack打包的代码如下(去掉了不必要的注释):

(function(modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.l = true;
        // Return the exports of the module
        return module.exports;
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // define getter function for harmony exports
    __webpack_require__.d = function(exports, name, getter) {
        if(!__webpack_require__.o(exports, name)) {
            Object.defineProperty(exports, name, {
                configurable: false,
                enumerable: true,
                get: getter
            });
        }
    };
    // getDefaultExport function for compatibility with non-harmony modules
    __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ?
            function getDefault() { return module['default']; } :
            function getModuleExports() { return module; };
        __webpack_require__.d(getter, 'a', getter);
        return getter;
    };
    // Object.prototype.hasOwnProperty.call
    __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(__webpack_require__.s = 0);
})
/************************************************************************/
([
/* 0 */
(function(module, exports, __webpack_require__) {

"use strict";

var bar = __webpack_require__(1);
bar.bar();

}),
/* 1 */
(function(module, exports, __webpack_require__) {

"use strict";

exports.bar = function () {
    return 1;
}

})
]);

分析

上面webpack打包的代码,整体可以简化成下面的结构:

(function (modules) {/* 省略函数内容 */})
([
function (module, exports, __webpack_require__) {
    /* 模块index.js的代码 */
},
function (module, exports, __webpack_require__) {
    /* 模块bar.js的代码 */
}
]);

可以看到,整个打包生成的代码是一个IIFE(立即执行函数),函数内容我们待会看,我们先来分析函数的参数。

函数参数是我们写的各个模块组成的数组,只不过我们的代码,被webpack包装在了一个函数的内部,也就是说我们的模块,在这里就是一个函数。为什么要这样做,是因为浏览器本身不支持模块化,那么webpack就用函数作用域来hack模块化的效果。

如果你debug过node代码,你会发现一样的hack方式,node中的模块也是函数,跟模块相关的参数exportsrequire,或者其他参数__filename__dirname等都是通过函数传值作为模块中的变量,模块与外部模块的访问就是通过这些参数进行的,当然这对开发者来说是透明的。

同样的方式,webpack也控制了模块的moduleexportsrequire,那么我们就看看webpack是如何实现这些功能的。

下面是摘取的函数内容,并添加了一些注释:

// 1、模块缓存对象
var installedModules = {};
// 2、webpack实现的require
function __webpack_require__(moduleId) {
    // 3、判断是否已缓存模块
    if(installedModules[moduleId]) {
        return installedModules[moduleId].exports;
    }
    // 4、缓存模块
    var module = installedModules[moduleId] = {
        i: moduleId,
        l: false,
        exports: {}
    };
    // 5、调用模块函数
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    // 6、标记模块为已加载
    module.l = true;
    // 7、返回module.exports
    return module.exports;
}
// 8、require第一个模块
return __webpack_require__(__webpack_require__.s = 0);

模块数组作为参数传入IIFE函数后,IIFE做了一些初始化工作:

  1. IIFE首先定义了installedModules ,这个变量被用来缓存已加载的模块。
  2. 定义了__webpack_require__ 这个函数,函数参数为模块的id。这个函数用来实现模块的require。
  3. __webpack_require__ 函数首先会检查是否缓存了已加载的模块,如果有则直接返回缓存模块的exports
  4. 如果没有缓存,也就是第一次加载,则首先初始化模块,并将模块进行缓存。
  5. 然后调用模块函数,也就是前面webpack对我们的模块的包装函数,将modulemodule.exports__webpack_require__作为参数传入。注意这里做了一个动态绑定,将模块函数的调用对象绑定为module.exports,这是为了保证在模块中的this指向当前模块。
  6. 调用完成后,模块标记为已加载。
  7. 返回模块exports的内容。
  8. 利用前面定义的__webpack_require__ 函数,require第0个模块,也就是入口模块。

require入口模块时,入口模块会收到收到三个参数,下面是入口模块代码:

function(module, exports, __webpack_require__) {
    "use strict";
    var bar = __webpack_require__(1);
    bar.bar();
}

webpack传入的第一个参数module是当前缓存的模块,包含当前模块的信息和exports;第二个参数exportsmodule.exports的引用,这也符合commonjs的规范;第三个__webpack_require__ 则是require的实现。

在我们的模块中,就可以对外使用module.exportsexports进行导出,使用__webpack_require__导入需要的模块,代码跟commonjs完全一样。

这样,就完成了对第一个模块的require,然后第一个模块会根据自己对其他模块的require,依次加载其他模块,最终形成一个依赖网状结构。webpack管理着这些模块的缓存,如果一个模块被require多次,那么只会有一次加载过程,而返回的是缓存的内容,这也是commonjs的规范。

结论

到这里,webpack就hack了commonjs代码。

原理还是很简单的,其实就是实现exportsrequire,然后自动加载入口模块,控制缓存模块,that's all。

细心的你一定会发现,文章到这里只介绍了webpack对commonjs的实现,那么ES6 module是如何实现的呢?
欢迎阅读本系列第二篇《webpack模块化原理-ES6 module》

查看原文

Dlyw 赞了文章 · 2019-12-02

webpack模块化原理-commonjs

我们都知道,webpack作为一个构建工具,解决了前端代码缺少模块化能力的问题。我们写的代码,经过webpack构建和包装之后,能够在浏览器以模块化的方式运行。这些能力,都是因为webpack对我们的代码进行了一层包装,本文就以webpack生成的代码入手,分析webpack是如何实现模块化的。

PS: webpack的模块不仅指js,包括css、图片等资源都可以以模块看待,但本文只关注js。

准备

首先我们创建一个简单入口模块index.js和一个依赖模块bar.js:

//index.js
'use strict';
var bar = require('./bar');
function foo() {
    return bar.bar();
}
//bar.js
'use strict';
exports.bar = function () {
    return 1;
}

webpack配置如下:

var path = require("path");
module.exports = {
    entry: path.join(__dirname, 'index.js'),
    output: {
        path: path.join(__dirname, 'outs'),
        filename: 'index.js'
    },
};

这是一个最简单的配置,只指定了模块入口和输出路径,但已经满足了我们的要求。

在根目录下执行webpack,得到经过webpack打包的代码如下(去掉了不必要的注释):

(function(modules) { // webpackBootstrap
    // The module cache
    var installedModules = {};
    // The require function
    function __webpack_require__(moduleId) {
        // Check if module is in cache
        if(installedModules[moduleId]) {
            return installedModules[moduleId].exports;
        }
        // Create a new module (and put it into the cache)
        var module = installedModules[moduleId] = {
            i: moduleId,
            l: false,
            exports: {}
        };
        // Execute the module function
        modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
        // Flag the module as loaded
        module.l = true;
        // Return the exports of the module
        return module.exports;
    }
    // expose the modules object (__webpack_modules__)
    __webpack_require__.m = modules;
    // expose the module cache
    __webpack_require__.c = installedModules;
    // define getter function for harmony exports
    __webpack_require__.d = function(exports, name, getter) {
        if(!__webpack_require__.o(exports, name)) {
            Object.defineProperty(exports, name, {
                configurable: false,
                enumerable: true,
                get: getter
            });
        }
    };
    // getDefaultExport function for compatibility with non-harmony modules
    __webpack_require__.n = function(module) {
        var getter = module && module.__esModule ?
            function getDefault() { return module['default']; } :
            function getModuleExports() { return module; };
        __webpack_require__.d(getter, 'a', getter);
        return getter;
    };
    // Object.prototype.hasOwnProperty.call
    __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
    // __webpack_public_path__
    __webpack_require__.p = "";
    // Load entry module and return exports
    return __webpack_require__(__webpack_require__.s = 0);
})
/************************************************************************/
([
/* 0 */
(function(module, exports, __webpack_require__) {

"use strict";

var bar = __webpack_require__(1);
bar.bar();

}),
/* 1 */
(function(module, exports, __webpack_require__) {

"use strict";

exports.bar = function () {
    return 1;
}

})
]);

分析

上面webpack打包的代码,整体可以简化成下面的结构:

(function (modules) {/* 省略函数内容 */})
([
function (module, exports, __webpack_require__) {
    /* 模块index.js的代码 */
},
function (module, exports, __webpack_require__) {
    /* 模块bar.js的代码 */
}
]);

可以看到,整个打包生成的代码是一个IIFE(立即执行函数),函数内容我们待会看,我们先来分析函数的参数。

函数参数是我们写的各个模块组成的数组,只不过我们的代码,被webpack包装在了一个函数的内部,也就是说我们的模块,在这里就是一个函数。为什么要这样做,是因为浏览器本身不支持模块化,那么webpack就用函数作用域来hack模块化的效果。

如果你debug过node代码,你会发现一样的hack方式,node中的模块也是函数,跟模块相关的参数exportsrequire,或者其他参数__filename__dirname等都是通过函数传值作为模块中的变量,模块与外部模块的访问就是通过这些参数进行的,当然这对开发者来说是透明的。

同样的方式,webpack也控制了模块的moduleexportsrequire,那么我们就看看webpack是如何实现这些功能的。

下面是摘取的函数内容,并添加了一些注释:

// 1、模块缓存对象
var installedModules = {};
// 2、webpack实现的require
function __webpack_require__(moduleId) {
    // 3、判断是否已缓存模块
    if(installedModules[moduleId]) {
        return installedModules[moduleId].exports;
    }
    // 4、缓存模块
    var module = installedModules[moduleId] = {
        i: moduleId,
        l: false,
        exports: {}
    };
    // 5、调用模块函数
    modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
    // 6、标记模块为已加载
    module.l = true;
    // 7、返回module.exports
    return module.exports;
}
// 8、require第一个模块
return __webpack_require__(__webpack_require__.s = 0);

模块数组作为参数传入IIFE函数后,IIFE做了一些初始化工作:

  1. IIFE首先定义了installedModules ,这个变量被用来缓存已加载的模块。
  2. 定义了__webpack_require__ 这个函数,函数参数为模块的id。这个函数用来实现模块的require。
  3. __webpack_require__ 函数首先会检查是否缓存了已加载的模块,如果有则直接返回缓存模块的exports
  4. 如果没有缓存,也就是第一次加载,则首先初始化模块,并将模块进行缓存。
  5. 然后调用模块函数,也就是前面webpack对我们的模块的包装函数,将modulemodule.exports__webpack_require__作为参数传入。注意这里做了一个动态绑定,将模块函数的调用对象绑定为module.exports,这是为了保证在模块中的this指向当前模块。
  6. 调用完成后,模块标记为已加载。
  7. 返回模块exports的内容。
  8. 利用前面定义的__webpack_require__ 函数,require第0个模块,也就是入口模块。

require入口模块时,入口模块会收到收到三个参数,下面是入口模块代码:

function(module, exports, __webpack_require__) {
    "use strict";
    var bar = __webpack_require__(1);
    bar.bar();
}

webpack传入的第一个参数module是当前缓存的模块,包含当前模块的信息和exports;第二个参数exportsmodule.exports的引用,这也符合commonjs的规范;第三个__webpack_require__ 则是require的实现。

在我们的模块中,就可以对外使用module.exportsexports进行导出,使用__webpack_require__导入需要的模块,代码跟commonjs完全一样。

这样,就完成了对第一个模块的require,然后第一个模块会根据自己对其他模块的require,依次加载其他模块,最终形成一个依赖网状结构。webpack管理着这些模块的缓存,如果一个模块被require多次,那么只会有一次加载过程,而返回的是缓存的内容,这也是commonjs的规范。

结论

到这里,webpack就hack了commonjs代码。

原理还是很简单的,其实就是实现exportsrequire,然后自动加载入口模块,控制缓存模块,that's all。

细心的你一定会发现,文章到这里只介绍了webpack对commonjs的实现,那么ES6 module是如何实现的呢?
欢迎阅读本系列第二篇《webpack模块化原理-ES6 module》

查看原文

赞 92 收藏 112 评论 10

Dlyw 收藏了文章 · 2019-03-20

Promise实现原理

前言

在Promise没有出现之前,异步编程需要通过回调的方式进行完成,当回调函数嵌套过多时,会使代码丑化,也降低了代码的可理解性,后期维护起来会相对困难,Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象,本文主要针对Promise/A+规范,实现一个小型的Promise对象。

Promise/A+ 规范

Promise规范有很多,如Promise/A,Promise/B,Promise/D 以及 Promise/A 的升级版Promise/A+,因为ES6主要用的是Promise/A+规范,该规范内容也比较多,我们挑几个简单的说明下:

  1. Promise本身是一个状态机,每一个Promise实例只能有三个状态,pendingfulfilledreject,状态之间的转化只能是pending->fulfilledpending->reject,状态变化不可逆。
  2. Promise有一个then方法,该方法可以被调用多次,并且返回一个Promise对象(返回新的Promise还是老的Promise对象,规范没有提)。
  3. 支持链式调用。
  4. 内部保存有一个value值,用来保存上次执行的结果值,如果报错,则保存的是异常信息。

具体规范可参考:

实现

由于Promise为状态机,我们需先定义状态

var PENDING = 0; // 进行中
var FULFILLED = 1; // 成功
var REJECTED = 2; // 失败

基本代码

function Promise(fn) {
  var state = PENDING;  // 存储PENDING, FULFILLED或者REJECTED的状态
  var value = null;  // 存储成功或失败的结果值
  var handlers = []; // 存储成功或失败的处理程序,通过调用`.then`或者`.done`方法

  // 成功状态变化
  function fulfill(result) {
      state = FULFILLED;
      value = result;
      handlers.forEach(handle); // 处理函数,下文会提到
      handlers = null;
   }

  // 失败状态变化
  function reject(error) {
      state = REJECTED;
      value = error;
      handlers.forEach(handle); // 处理函数,下文会提到
      handlers = null;
  }
}

实现resolve方法

resolve方法可以接受两种参数,一种为普通的值/对象,另外一种为一个Promise对象,如果是普通的值/对象,则直接把结果传递到下一个对象;
如果是一个 Promise 对象,则必须先等待这个子任务序列完成。

function Promise(fn) {
  ...
  function resolve(result) {
      try {
        var then = getThen(result);
        if (then) {
          doResolve(then.bind(result), resolve, reject)
          return;
        }
        fulfill(result);
      } catch (e) {
        reject(e);
      }
  }
  ...
}

resolve需要两个辅助方法getThen、和doResolve

// getThen 检查如果value是一个Promise对象,则返回then方法等待执行完成。
function getThen(value) {
  var t = typeof value;
  if (value && (t === 'object' || t === 'function')) {
    var then = value.then;
    if (typeof then === 'function') {
      return then;
    }
  }
  return null;
}
// 异常参数检查函数,确保onFulfilled和onRejected两个函数中只执行一个且只执行一次,但是不保证异步。
function doResolve(fn, onFulfilled, onRejected) {
  var done = false;
  try {
    fn(
      function(value) {
        if (done) return;
        done = true;
        onFulfilled(value);
      },
      function(reason) {
        if (done) return;
        done = true;
        onRejected(reason);
      }
    );
  } catch(ex) {
    if (done) return;
    done = true;
    onRejected(ex);
  }
}

上面已经完成了一个完整的内部状态机,但我们并没有暴露一个方法去解析或则观察 Promise 。现在让我们开始解析 Promise :

function Promise(fn) {
  ...
  doResolve(fn, resolve, reject);
}

如你所见,我们复用了doResolve,因为对于初始化的fn也要对其进行控制。fn允许调用resolve或则reject多次,甚至抛出异常。这完全取决于我们去保证promise对象仅被resolved或则rejected一次,且状态不能随意改变。

then方法实现

在实现then方法之前,我们这里实现了一个执行方法done,该方法用来处理执行then方法的回调函数,一下为promise.done(onFullfilled, onRejected)方法的几个点。

  • onFulfilled 和 onRejected 两者只能有一个被执行,且执行次数为一
  • 该方法仅能被调用一次, 一旦调用了该方法,则 promise 链式调用结束
  • 无论是否 promise 已经被解析,都可以调用该方法
function Promise(fn) {
  ...
  // 不同状态,进行不同的处理
  function handle(handler) {
    if (state === PENDING) {
      handlers.push(handler);
    } else {
      if (state === FULFILLED && typeof handler.onFulfilled === 'function') {
        handler.onFulfilled(value);
      }
      if (state === REJECTED && typeof handler.onRejected === 'function') {
        handler.onRejected(value);
      }
    }
  }

  this.done = function (onFulfilled, onRejected) {
    // 保证异步
    setTimeout(function () {
      handle({onFulfilled: onFulfilled, onRejected: onRejected});
    }, 0);
  }
}

当 Promise 被 resolved 或者 rejected 时,我们保证 handlers 将被通知。
then方法

function Promise(fn) {
  ...
  this.then = function(onFulfilled, onRejected) {
    var self = this;
    return new Promise(function (resolve, reject) {
      self.done(function (result) {
        if (typeof onFulfilled === 'function') {
          try {
            // onFulfilled方法要有返回值!
            return resolve(onFulfilled(result));
          } catch (ex) {
            return reject(ex);
          }
        } else {
          return resolve(result);
        }
      }, function (error) {
        if (typeof onRejected === 'function') {
          try {
            return resolve(onRejected(error));
          } catch (ex) {
            return reject(ex);
          }
        } else {
          return reject(error);
        }
      });
    });
  }
}

catch方法,我们直接调用then处理异常

this.catch = function(errorHandle) {
  return this.then(null, errorHandle);
}

以上为promise实现原理~

查看原文

认证与成就

  • 获得 0 次点赞
  • 获得 0 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 0 枚铜徽章

擅长技能
编辑

(゚∀゚ )
暂时没有

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2018-12-16
个人主页被 43 人浏览