【编程语言】 C++高级特性及实战

主要记录C++相关重要的知识点及优秀实践

References

优秀开源

Abseil

  • Abseil 是一个由 Google 开源的 C++/python 库,提供了一组常用的工具和基础设施,用于补充 C++ 标准库中缺失的功能或提高效率。
  • C++17的string_view前身就是来自absl::string_view
  • abseil-cpp

Dlib

  • Dlib 是一个流行的 C++ 库,主要用于机器学习、计算机视觉和图像处理。它提供了丰富的机器学习功能,支持多种算法和优化方法。
  • dlib

XGBoost

  • XGBoost 是一个高效的机器学习库,特别适用于梯度提升决策树(GBDT)算法,广泛用于回归、分类和排序任务。
  • xgboost

Google’s glog (Google Logging Library)

  • 功能:glog 是一个 C++ 日志库,提供了强大的日志记录功能,包括日志级别(DEBUG、INFO、WARNING、ERROR 和 FATAL)、日志输出到文件、以及日志格式化。
  • 特点:简单易用,支持日志级别设置、日志输出的细粒度控制,还可以在生产环境中非常高效地记录日志。
  • 链接:glog GitHub

spdlog

  • 功能:spdlog 是一个非常快速的 C++ 日志库,旨在提供低延迟、高性能的日志记录功能。
  • 特点:spdlog 提供线程安全的日志记录支持,能够输出到控制台或文件,支持日志级别、日志格式等功能。
  • 链接:spdlog GitHub

folly (Facebook Open-source Library)

  • 功能:folly 是 Facebook 开发的一个 C++ 库,包含了许多高性能的组件和工具,适用于大规模系统的开发。它包括内存管理、并发、容器、算法、IO等多个方面的扩展。
  • 特点:folly 提供了大量与系统底层交互的工具,具有很高的性能,适用于对性能要求极高的应用。
  • 链接:folly GitHub

Boost

  • 功能:Boost 是一个广泛使用的 C++ 库集合,提供了许多扩展标准库的功能,包括智能指针、正则表达式、线程、文件系统、算法等。
  • 特点:Boost 提供了丰富的功能,经过多年的开发和优化,成为了 C++ 生态中非常重要的工具库之一。很多 C++ 标准库中的特性都源自 Boost(如 std::shared_ptr 和 std::filesystem)。
  • c++17中的std::filesystem、std::any、std::varient等直接来自于boost中。boost::program_options用于处理控制台的输入参数也是很方便
  • 链接:Boost官网

fmt

  • 功能:fmt 是一个现代化的、快速的格式化库,提供了类似 Python 中的 f-string 或 C# 中的 string interpolation 的功能。
  • 特点:它允许开发者使用更加简洁和类型安全的方式进行字符串格式化。fmt 库的速度非常快,而且 API 设计符合现代 C++ 风格。
  • 链接:fmt GitHub

gflags

  • 功能:gflags 是一个 Google 提供的命令行参数解析库,广泛用于解析应用程序启动时的命令行选项。
  • 特点:gflags 提供了易于使用的命令行选项定义和管理功能,支持复杂的命令行解析需求,例如布尔值选项、枚举类型选项等。
  • 链接:gflags GitHub

tbb (Threading Building Blocks)

  • 功能:tbb 是 Intel 提供的一个 C++ 并行编程库,旨在帮助开发者利用多核处理器,简化并行编程。
  • 特点:提供了线程池、并行算法和数据结构,能够方便地进行并行化计算,且通过自动负载平衡使多核资源得到高效利用。
  • 链接:TBB GitHub

cppcoro

  • 功能:cppcoro 是一个支持 C++20 协程的 C++ 库,提供了多种并发控制结构,如 task 和 awaiter,用于协程的高效实现。
  • 特点:使 C++ 开发者能够高效地编写异步代码,同时保持代码简洁和易于理解。适合需要异步操作的场景。
  • 链接:cppcoro GitHub

Eigen

  • 功能:Eigen 是一个高效的 C++ 数学库,专门用于矩阵运算、线性代数和数值计算。
  • 特点:Eigen 提供了一个高性能的模板库,支持多维数组、矩阵操作以及高级的线性代数功能,广泛用于科学计算、机器学习等领域。
  • 链接:Eigen GitHub

C++语言参考

类和结构(class and struct)

类成员

  • override:重写父类虚函数
  • final:表示一个虚函数不能被进一步重写,或者表示一个类不能被继承
  • delete:禁用某个函数,如默认构造
  • default:明确地请求编译器为类生成默认实现
  • explicit:防止隐式转换调用其他函数
  • 纯虚函数:virtual void doStep() = 0; // 要求派生类必须实现,否则派生类也将变成抽象类,无法实例化。
  • 常成员函数const:只能调用其他常成员函数,不能修改成员变量(除mutable)
  • static静态成员函数:不用实例化,可被直接调用
  • inline:内联请求,将代码插入调用函数处,较少调用栈开销
  • noexcept:表示该函数不会抛出异常
  • mutable:修饰变量可在常成员函数中修改
  • constexpr:表示该函数在编译时计算结果
  • friend:友元函数/类,允许外部函数或类在需要时访问类的私有实现
  • operator :用于定义或重载类的运算符
  • 自定义迭代器类:通常需重载==、!=、++、*解引用,实现begin、end

三/五/零之法则(rule of three)

  • 因为C++类的特殊成员特性在实际应用可能产生用户非预期的效果,所以总结为法则用以规避可能出现的潜在风险
  • cpp references

资源获取即初始化(Resource Acquisition Is Initialization, RAAI)

  • 与托管语言不同,C++ 没有自动回收垃圾机制,易导致内存泄露
  • C++ 将资源的生命周期与对象的生命周期所绑定(构造获取资源/析构释放资源,利用了栈上的变量在离开作用域的时候会析构的特性)
  • c++11后的四大smart_point(shared_ptr、unique_ptr、weak_ptr、auto_ptr(在17中废除))采用了这种思想
  • 善于利用析构特性进行自动内存回收管理,如std::lock_guard、Std::make_unique、Std::make_share等

运行时类型识别(Run Time Type Identification,RTTI)

  • c++中RTTI的一些体现typeid、dynamic_cast、type traits 具体可以看runtime的库的函数__RTtypeid,rtti把所需的type_info(不同编译器会有所不同)信息放在vtable前,大概也是dynamic_cast要求父类必须有虚函数的原因吧
  • 注意,取虚函数表地址时 (此处请注意环境在32位和64位下的区别,在32/64位下取对象a(带有虚函数的基类的实例)的首地址(虚函数表地址)有区分,即(int )&a 和 (long )&a的不同,为避免也可直接,(int(int)(&classname)替换成(intptr_t(intptr_t)(&classname))**

用于编译时封装的 Pimpl

Pimpl(Pointer to Implementation)是一种设计模式,常用于C++编程中以隐藏类的实现细节。Pimpl模式通过将实现细节移到一个私有的实现类中,从而提高代码的可维护性、降低编译时间以及实现二进制兼容性。

  • 编译依赖项的最小化。
  • 接口和实现的分离。
  • 可移植性。 一般实现:
1
2
3
4
5
6
7
// 头文件定义private类指针,源文件进行实现类impl
// my_class.h
class my_class {
   //  ... all public and protected stuff goes here ...
private:
   class impl; unique_ptr<impl> pimpl; // opaque type here
};

匿名函数 lambda表达式

引用 reference

指针

异常

模板 template

  • 变长参数模板:
1
2
3
4
5
template <typename... Modules>
  explicit Sequential(Modules &&...modules) {
    modules_.reserve(sizeof...(Modules));
    pushBack(std::forward<Modules>(modules)...);
  } // 递归展开,调用基础pushBack方法
  • 完美转发:std::forward,保留原来值类型(左值/右值)
  • std::optional:处理可能为null等值情况
  • std::enable_shared_from_this:在对象的成员函数中获取指向自身的智能指针,增加对象的引用计数,确保对象在异步操作或回调过程中不会被销毁

STL(Standard Template Library,标准模板库)

容器(Containers)

  • vector.reserve 和 resize
  • Vecotr.emplace_back和push_back
  • std::reference_wrapper存储引用
  • std::initializer_list 轻量级初始化列表,不可修改;

算法(Algorithms)

迭代器(Iterators)

函数对象(Function Objects)

C++ 14新特性

C++ 17新特性

并行算法库

1
2
3
4
5
6
7
8
#include <algorithm>
#include <execution>
// std::sort(begin, end, comp); // origin
std::sort(exe_policy, begin, end, comp);
// 执行策略(execution policy)可选:
// 1、std::execution::seq(顺序执行)
// 2、std::execution::par(并行执行)
// 3、std::execution::par_unseq(并行和向量化执行)

C++ 20新特性

其他

宏定义

#、#@、##、VA_ARGS 应用

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#define Conn(x,y)  x##y // 表示x连接y
#define ToChar(x)  #@x  // 给x加上单引号
#define ToString(x) #x  // 给x加上双引号

char* str = ToString(123132);     // str="123132";
int n = Conn(123,456);            //n=123456;
char* str = Conn("asdf", "add")   //str = "asdfadf";
char a = ToChar(1);               // a='1';
// char a = ToChar(123);          // 编译器报错
#define debug(...) printf(__VA_ARGS__) // 用于宏定义中代表可变参数

运行时类型反射(Run Time Type Reflection, RTTR)

  • 反射是一个进程检查、反省和修改其自身结构和行为的能力
  • 众所周知,java、c#、Go等语言在语言层面支持了反射特性。而c++不支持反射,因为C++没有在语言层面提供返回类的metadata的能力,所以很多属性要靠手动注册,于是乎有人自造轮子搞了个反射机制(UE中的U++通过UHT和UBT来支持反射)
Licensed under CC BY-NC-SA 4.0
最后更新于 Feb 23, 2025 11:00 +0800
loveleaves
使用 Hugo 构建
主题 StackJimmy 设计