有哪些优秀的 C++ 代码库可以保举学习?
我是大学一年级学生,想更多地了解 C++。 只推荐3个基础库,都是工业级的:1、poco:最朴实无华的c艹基础库,非常易懂,大多数实现初学者看起来毫无压力;功能也非常全面,功能集相当于一个小Qt;目前很火的ClickHouse里面也用到了。学完这个里面的东西,对于一般c艹应用开发绝对够了。缺点可能就是由于实现朴实有些地方可能性能不够好(不过这是个取舍的问题,CH性能很好不也用了poco,如果发现性能问题的地方可以换做其他的),还有就是实现可能不够modern。
2、abseil:Google出品的基础库,对stl的补充,这个非常推荐给在用c++11但不具备c++17条件的使用,因为里面实现了一部分c++17,甚至20的特性,比如any、variant、optiona、span等等;顶级水平,足够现代。
3、folly:Meta(FB)的基础库,功能比较丰富,提供了一些极尽优化追求性能的实现,看起来难度大。顶流水准,风格现代(不过一股浓浓的java风,我喜欢,哈哈哈,部分实现也是参考java的),里面不乏c艹界大师级人物的贡献,如Andrei Alexandrescu。由于难道大,不建议没有多少经验的人看,要看挑部分看看吧。同时推荐wangle和proxgen,同是FB的,这2个是基于folly的,可以作为运用folly的示例。
ps:本人水平低,只看了大部分poco,abseil和folly看了一丢丢(当然也没打算看完,哈哈哈哈)。
最后不建议大家看很多源码,人生苦短,后一句就不说了…. coost-A tiny boost library in C++11coost 是一个兼具性能与易用性的跨平台 C++ 基础库,其目标是打造一把 C++ 开发神器,让 C++ 编程变得简单、轻松、愉快。
coost 原名为 co,后改为 cocoyaxi,前者过短,后者过长,取中庸之道,又改为 coost。它曾被称为小型 boost 库,与 boost 相比,coost 小而精美,在 linux 与 mac 上编译出来的静态库仅 1M 左右大小,却包含了不少强大的功能:
[*]命令行与配置文件解析(flag)
[*]高性能日志库(log)
[*]单元测试框架(unitest)
[*]go-style 协程
[*]基于协程的网络编程框架
[*]高效 JSON 库
[*]基于 JSON 的 RPC 框架
[*]原子操作(atomic)
[*]高效字符流(fastream)
[*]高效字符串(fastring)
[*]字符串操作(str)
[*]时间库(time)
[*]线程库(thread)
[*]定时任务调度器
[*]面向玄学编程
[*]LruMap
[*]hash 库
[*]path 库
[*]文件系统操作(fs)
[*]系统操作(os)
[*]高性能内存分配器
coost 的发展历程
[*]2013-2015 年,Alvin(idealvin) 在使用 google gflags、glog、gtest 等时,感到有些繁琐,就自己动手实现了相应的功能,即现今 coost 中的 flag、log、unitest 等组件。
[*]2015-2018 年,Alvin 将自研的这套基础库引入实际项目中,供自己与同事使用,大幅度提升了 C++ 开发效率,coost 也得以经受工业项目的检验,并在实践中不断完善、扩充新的功能。
[*]2019 年,Alvin 实现了类似 goroutine 的协程机制,以及基于协程的网络编程框架,之后将项目命名为 co,在 github 上发布 1.0 版本。
[*]2020-2021 年,完善 hook 机制、协程同步机制,增加 golang 中的 channel、defer 等特性,发布 2.x 版本。在此期间,码友们提供了很多宝贵的改进意见,并帮忙完善了 xmake、cmake 编译脚本以及 coost 中的很多功能。
[*]2022 年,新增内存分配器、提升整体性能,对 flag、log、JSON、RPC、fastring、fastream 等很多组件做出了重大改进,并将项目更名为 coost,发布 3.0 版本。
快速上手
编译
建议安装 xmake,在 coost 根目录执行如下命令构建所有子项目:
xmake -a如果需要使用 http::Client, SSL 或 HTTPS 特性,则可以用下面的命令构建:
xmake f --with_libcurl=true --with_openssl=true
xmake -axmake 会自动从网络安装 libcurl 与 openssl,视网络情况,这个过程可能会较慢。xmake -a会编译libco,gen,unitest以及test目录下面的所有测试代码。编译完后可以执行如下命令,运行 coost 中的测试程序:
xmake r unitest
xmake r flag
xmake r log -cout
xmake r co使用 coost 开发 C++ 项目
最简单的,可以直接包含co/all.h,使用 coost 中的所有特性。如果担心影响编译速度,也可以只包含需要用到的头文件,如包含co/co.h,可以使用 co/flag, co/log 以及协程相关的所有特性。
#include "co/all.h"
DEF_string(s, "nice", "");
int main(int argc, char** argv) {
flag::init(argc, argv);
LOG << FLG_s;
return 0;
}
上面是一个简单的例子,main 函数第一行用于解析命令行参数及配置文件。coost 中的部分组件用 flag 定义配置项,因此需要在 main 函数开头调用 flag::init() 进行初始化。
用户也可以用宏 DEF_main 定义 main 函数:
#include &#34;co/all.h&#34;
DEF_string(s, &#34;nice&#34;, &#34;&#34;);
DEF_main(argc, argv) {
LOG << FLG_s;
return 0;
}
DEF_main将 main 函数中的代码放到协程中运行,内部已经调用了flag::init(),用户无需手动调用。
核心组件
co/flag
co/flag 是一个简单易用的命令行参数与配置文件解析库,cocoyaxi 中的一些组件会用它定义配置项。
co/flag 为每个配置项提供一个默认值,在没有配置参数的情况下,程序可以按默认配置运行。用户也可以从命令行或配置文件传入配置参数,在需要配置文件时,可以执行 ./exe -mkconf 自动生成配置文件。
// xx.cc
#include &#34;co/flag.h&#34;
#include &#34;co/log.h&#34;
DEF_bool(x, false, &#34;bool x&#34;);
DEF_bool(y, false, &#34;bool y&#34;);
DEF_uint32(u32, 0, &#34;...&#34;);
DEF_string(s, &#34;hello world&#34;, &#34;string&#34;);
int main(int argc, char** argv) {
flag::init(argc, argv);
COUT << &#34;x: &#34; << FLG_x;
COUT << &#34;y: &#34; << FLG_y;
COUT << &#34;u32: &#34; << FLG_u32;
COUT << FLG_s << &#34;|&#34; << FLG_s.size();
return 0;
}
上面是一个使用 co/flag 的例子,代码中 DEF_ 开头的宏,定义了 4 个配置项,每个配置项相当于一个全局变量,变量名是 FLG_ 加配置名。上面的代码编译完后,可以按下面的方式运行:
./xx # 按默认配置运行
./xx -xy -s good # 单字母命名的 bool flag, 可以一并设置为 true
./xx -s &#34;I&#39;m ok&#34; # 含空格的字符串
./xx -u32 8k # 整数可以带单位: k,m,g,t,p, 不区分大小写
./xx -mkconf # 自动生成配置文件 xx.conf
./xx xx.conf # 从配置文件传入参数
./xx -config xx.conf# 与上同co/log
co/log 是一个高性能的本地日志系统,cocoyaxi 中的一些组件会用它打印日志。
co/log 将日志分为 debug, info, warning, error, fatal 5 个级别,打印 fatal 级别的日志会终止程序的运行。用户可以像下面这样打印不同级别的日志:
DLOG << &#34;hello &#34; << 23;// debug
LOG << &#34;hello &#34; << 23; // info
WLOG << &#34;hello &#34; << 23;// warning
ELOG << &#34;hello &#34; << 23;// error
FLOG << &#34;hello &#34; << 23;// fatal
co/log 还提供了一系列 CHECK 宏,可以视为加强版的 assert,它们在 debug 模式下也不会被清除。
void* p = malloc(32);
CHECK(p != NULL) << &#34;malloc failed..&#34;;
CHECK_NE(p, NULL) << &#34;malloc failed..&#34;;
CHECK 断言失败时,co/log 会打印函数调用栈信息,然后终止程序的运行。
(asciicast:435894 - asciinema)
co/log 速度非常快,在程序运行稳定后,几乎不需要内存分配操作。下面是一些测试结果,仅供参考:
[*]co/log vs glog (single thread)
[*]co/log vs spdlog (Windows)
[*]co/log vs spdlog (Linux)
co/unitest
unitest 是一个简单易用的单元测试框架,cocoyaxi 中的很多组件会用它写单元测试代码,为 cocoyaxi 的稳定性提供了保障。
#include &#34;co/unitest.h&#34;
#include &#34;co/os.h&#34;
namespace test {
DEF_test(os) {
DEF_case(homedir) {
EXPECT_NE(os::homedir(), &#34;&#34;);
}
DEF_case(cpunum) {
EXPECT_GT(os::cpunum(), 0);
}
}
} // namespace test
上面是一个简单的例子,DEF_test 宏定义了一个测试单元,实际上就是一个函数(类中的方法)。DEF_case 宏定义了测试用例,每个测试用例实际上就是一个代码块。多个测试单元可以放到同一个 C++ 项目中,main 函数一般只需要下面几行:
#include &#34;co/unitest.h&#34;
int main(int argc, char** argv) {
flag::init(argc, argv);
unitest::run_all_tests();
return 0;
}
unitest 目录下面是 cocoyaxi 中的单元测试代码,编译后可执行下述命令运行:
xmake r unitest -a # 运行所有单元测试用例
xmake r unitest -os# 仅运行 os 单元中的测试用例协程
cocoyaxi 实现了类似 golang 的协程,它有如下特性:
[*]多线程调度,默认线程数为系统 CPU 核数。
[*]共享栈,同一线程中的协程共用若干个栈(大小默认为 1MB),内存占用低,Linux 上的测试显示 1000 万协程只用了 2.8G 内存(仅供参考)。
[*]各协程之间为平级关系,可以在任何地方(包括在协程中)创建新的协程。
[*]支持系统 API hook (Windows/Linux/Mac),可以直接在协程中使用三方网络库。
[*]协程化的 socket API。
[*]协程同步事件 co::Event。
[*]协程锁 co::Mutex。
[*]协程池 co::Pool。
[*]channel co::Chan。
[*]waitgroup co::WaitGroup。
创建协程
go(ku); // void ku();
go(f, 7); // void f(int);
go(&T::f, &o); // void T::f(); T o;
go(&T::f, &o, 7);// void T::f(int); T o;
go([](){
LOG << &#34;hello go&#34;;
});
上面是用 go() 创建协程的例子,go() 是一个函数,它接受 1 到 3 个参数,第一个参数 f 是任意可调用的对象,这些参数只要满足 f(), (*f)(), f(p), (*f)(p), (o->*f)() 或者 (o->*f)(p) 能被调用就可以了。
go() 创建的协程会均匀的分配到不同的调度线程中。如果用户想让某些协程运行在同一个线程下,可以用下面的方式创建协程:
auto s = co::next_scheduler();
s->go(f1);
s->go(f2);
如果用户想在所有的调度线程中创建协程,可以用下面的方式:
auto& s = co::all_schedulers();
for (size_t i = 0; i < s.size(); ++i) {
s->go(f);
}
channel
co::Chan,类似于 golang 中的 channel,可用于在协程之间传递数据。
#include &#34;co/co.h&#34;
DEF_main(argc, argv) {
co::Chan<int> ch;
go(() {
ch << 7;
});
int v = 0;
ch >> v;
LOG << &#34;v: &#34; << v;
return 0;
}
channel 的读写操作必须在协程中进行,因此上述代码中用 DEF_main 定义 main 函数,让 main 函数中的代码也运行在协程中。
代码中的 channel 对象在栈上,而 cocoyaxi 采用的是共享栈实现方式,一个协程栈上的数据可能被其他协程覆盖,协程间一般不能直接通过栈上的数据通信,因此代码中的 lambda 采用了按值捕获的方式,将 channel 拷贝了一份,传递到新建的协程中。channel 的拷贝操作只是将内部引用计数加 1,几乎不会对性能造成影响。
创建 channel 时可以像下面这样加上超时时间:
co::Chan<int> ch(8, 1000);
channel 读写操作结束后,可以调用 co::timeout() 判断是否超时,这种方式比 golang 中基于 select 的实现方式更简单。
cocoyaxi 中的 channel 基于内存拷贝实现,传递的数据类型可以是内置类型、指针类型,或者拷贝操作具有简单的内存拷贝语义的结构体类型。像 std::string 或 STL 中的容器类型,拷贝操作不是简单的内存拷贝,一般不能直接在 channel 中传递,详情见 co::Chan 参考文档。
waitgroup
co::WaitGroup,类似于 golang 中的 sync.WaitGroup,可用于等待协程或线程的退出。
#include &#34;co/co.h&#34;
DEF_main(argc, argv) {
FLG_cout = true;
co::WaitGroup wg;
wg.add(8);
for (int i = 0; i < 8; ++i) {
go(() {
LOG << &#34;co: &#34; << co::coroutine_id();
wg.done();
});
}
wg.wait();
return 0;
}
网络编程
cocoyaxi 提供了一套协程化的 socket API,它们大部分形式上与原生的 socket API 基本一致,熟悉 socket 编程的用户,可以轻松的用同步的方式写出高性能的网络程序。另外,cocoyaxi 也实现了更高层的网络编程组件,包括 TCP、HTTP 以及基于 JSON 的 RPC 框架,它们兼容 IPv6,同时支持 SSL,用起来比 socket API 更方便。这里只简单的展示一下 HTTP 的用法,其余的可以查看参考文档。
静态 web server
#include &#34;co/flag.h&#34;
#include &#34;co/log.h&#34;
#include &#34;co/so.h&#34;
DEF_string(d, &#34;.&#34;, &#34;root dir&#34;); // Specify the root directory of the web server
int main(int argc, char** argv) {
flag::init(argc, argv);
log::init();
so::easy(FLG_d.c_str()); // mum never have to worry again
return 0;
}
HTTP server
http::Server serv;
serv.on_req(
[](const http::Req& req, http::Res& res) {
if (req.is_method_get()) {
if (req.url() == &#34;/hello&#34;) {
res.set_status(200);
res.set_body(&#34;hello world&#34;);
} else {
res.set_status(404);
}
} else {
res.set_status(405); // method not allowed
}
}
);
serv.start(&#34;0.0.0.0&#34;, 80); // http
serv.start(&#34;0.0.0.0&#34;, 443, &#34;privkey.pem&#34;, &#34;certificate.pem&#34;); // https
HTTP client
void f() {
http::Client c(&#34;https://github.com&#34;);
c.get(&#34;/&#34;);
LOG << &#34;response code: &#34;<< c.response_code();
LOG << &#34;body size: &#34;<< c.body_size();
LOG << &#34;Content-Length: &#34;<< c.header(&#34;Content-Length&#34;);
LOG << c.header();
c.post(&#34;/hello&#34;, &#34;data xxx&#34;);
LOG << &#34;response code: &#34;<< c.response_code();
}
go(f); 开源C ++库的综合列表:
1、通用
[*]Boost - 大量通用库
[*]Dlib -网络、线程、图形界面、数据结构、线性代数、机器学习、XML和文本解析、数值优化、贝叶斯网络等(Boost许可证)
[*]JUCE -广泛、成熟、跨平台的C ++工具包(GPL许可证)
[*]Folly -Facebook开源库
[*]Abseil -来自Google C ++库代码的开源集合
[*]cxxomfort - C ++的Backports功能
[*]Ultimate++ -跨平台的快速应用程序开发框架
[*]CAF
[*]Better Enums - 具有constexpr支持的反射枚举
[*]Smart Enum - “to_string”,“from_string”以及更多内容
2、通讯
[*]libnavajo - 轻巧但功能强大的API,包括用于Web和RESTful应用程序开发的http服务器,支持SSL、身份验证、cookie和会话管理,包括Websocket服务器支持
[*]C++ RESTful framework - C ++微框架,旨在嵌入到广泛的应用程序中
[*]CPR - 现代C ++ HTTP请求库
[*]cpp-netlib - C ++网络库
[*]cpp-redis - C ++ 11 Lightweight Redis客户端
[*]tacopie - C ++ 11 TCP库
[*]Boost.Beast - 建立在Boost.Asio之上的HTTP和WebSocket库
[*]gsoap -用于XML数据绑定的C / C ++开发工具包
[*]omniORB - C ++中最快,最完整,最便携的CORBA ORB实现
[*]Unicomm -异步网络,高级TCP通信框架
[*]zeromq -快速消息队列
[*]libashttp -异步HTTP客户端库
[*]The Silicon C++14 Web Framework - 快速而强大的Web API(MIT)
3、图形用户界面
[*]Dear ImGui
[*]FLTK
[*]nana[doc] - 现代C ++风格的GUI编程
[*]OWLNext
[*]Switch
GTK+
[*]glibmm
[*]gtkmm
[*]goocanvasmm
[*]libglademm
[*]libgnomecanvasmm
[*]webkitgtk
[*]flowcanvas
[*]evince
Qt
[*]Qt[ src ] [ doc ]
[*]qwt5
[*]libdbusmenu-QT
[*]QuickQanava - 用于在Qt / QML应用程序中绘制有向图的C ++ 14库
[*]QuickProperties - 用于QObject / QtObject属性版的C ++ / QML库
4、通用多媒体
[*]SFM - 简单快速多媒体库
[*]SDL -通过图形API(通常为OpenGL或Direct3D)跨平台访问音频、键盘、鼠标、操纵杆和图形硬件
[*]SIGIL -用于文本、形状、输入、音频和2D图像的跨平台库
[*]Cinder
[*]openFrameworks
5、图像
[*]cairomm
[*]nux
[*]pangomm
[*]gegl
[*]stb
[*]Adobe/boost GIL -高级通用库,专注于对2D图像进行操作的算法
[*]GraphicsMagick - 以超过88种格式读取、书写和操作图像。
[*]Skia Graphics Engine - Google的核心图形库
绘制
[*]plotutils
格式
[*]libraw
[*]openexr
[*]qimageblitz
[*]imagemagick
[*]djvulibre
[*]poppler
[*]SVG++
6、音频
[*]soundtouch
[*]KFR - 快速、现代的DSP架构,DFT / FFT,音频重采样,FIR / IIR滤波器,Biquad
[*]Aquila - 跨平台DSP库
7、图像处理
[*]OpenCV
[*]DLIB
[*]ITK
[*]OTB
8、视频
[*]crystalhd
[*]mjpegtools
[*]libmatroska
[*]libVLC
[*]gstreamermm
9、3D图形
[*]Vulkan
[*]OpenGL
[*]bgfx - “自带引擎/框架”样式渲染库
[*]Ogre3D
[*]Diligent Engine- 一个现代的跨平台低级3D图形库。
[*]GLEW - OpenGL函数加载
[*]GLAD - 可自定义的轻量级库,用于加载OpenGL函数
[*]Visionaray - C ++光线跟踪模板库
10、游戏引擎架构
[*]EntityX
[*]ANAX
[*]EntityPlus
[*]EnTT
[*]Box2D- 物理引擎
11、数学
线性代数
[*]Boost.uBLAS
[*]Eigen
[*]Armadillo
[*]Blitz++
[*]IT++
[*]Dlib - linear algebra tools
[*]Blaze
[*]ETL
优化
OptimLib - 用于非线性函数的C ++ 11数值优化方法库。
12、机器学习
[*]stats++
[*]liblinear
[*]Dlib -机器学习工具
[*]MLPACK - 机器学习包
[*]Shogun - 大型机器学习工具箱
13、容器
[*]Boost.Any
[*]Boost.Array
[*]Boost.Bimap
[*]Boost.Container
[*]Boost.Fusion
[*]Boost.Heap
[*]Boost.Pointer容器
[*]Boost.Tuple
[*]Boost.Variant
14、数据库
[*]OTL
[*]DTL
[*]libpqxx
[*]lmdb ++ - 用于LMDB嵌入式B +树数据库库的C ++ 11包装器。
[*]mongocxx - MongoDB的C ++ 11驱动程序库
[*]MySQL的++
[*]ODB - C ++对象关系映射(ORM)
[*]Pgfe - PostGres FrontEnd - PostgreSQL的现代C ++客户端API
15、测试
[*]Boost.Test
[*]cppunit
[*]Google Test
[*]Catch2
16、嵌入式/实时
[*]QP / C ++ - RTOS内核,双GPL
[*]FreeRTOS C ++处理程序 - 处理程序,循环器,状态机,CLI,便携式
[*]ETL - 嵌入式模板库 - C ++ 03,为低资源平台量身定制的便携式模板库
[*]distortos - 面向对象的C ++ RTOS,用于微控制器
[*]μcuREST - 用于微控制器的C ++ 11 REST / JSON服务器框架
练习C++:
[*]C++11/14 高速上手教程
[*]C++ 实现俄罗斯方块
[*]C++ 实现太阳系行星系统
[*]C++实现课程管理系统
[*]C++ 开发 Web 服务框架
[*]C++ 基于 OpenCV 实现实时监控和运动检测记录
摘自:A list of open source C++ libraries - cppreference
更多优秀的学习资源,尽在 实验楼~
精选 22 个 C++ 项目,推荐新人练手首选!收藏的时候别忘了点个赞呐(`・ω・´) fffaraz/awesome-cpp足够从初学一直用到工作很久,甚至可能一直用到不再用C++为止…… RapidJSON,一个JSON的解析器,高度模板化,全头文件。 @Milo Yip
页:
[1]