Advent of Compiler Optimisations 20255 months agohttps://xania.org/202511/advent-of-compiler-optimisation宣布推出《编译器优化降临历2025》(AoCO2025),这是从12月1日至25日每日更新的博客与视频系列。每天将讲解一个C或C++编译器优化技术,涵盖适用场景、汇编解析及局限性等细节。内容既包含底层架构专属技巧(主要侧重x86-64架构,部分涉及ARM),也涵盖高级优化策略。可通过AoCO2025博客标签、YouTube订阅或播放列表追踪更新。该项目凝聚了一年研究成果,旨在分享编译器技术洞见与开发热情。
Trying Out C++26 Executors6 months agohttps://mropert.github.io/2025/11/21/trying_out_stdexec/作者探讨了如何利用C++的并发特性改进游戏启动时间他们在Vulkan渲染器项目中尝试使用C++26执行器实现并行任务传统方法(TBB)与C++26执行器的对比测试结果喜忧参半C++26执行器存在冗长代码、潜在静默失败和并行执行保证不明确等问题作者认为C++26执行器可能尚未达到标准化条件,建议进行更多实际场景测试
Mirror_bridge – C++ reflection for generating Python/JS/Lua bindings5 months agohttps://chico.dev/Mirror-Bridge/Mirror Bridge 无需手动编写样板代码即可简化C++代码的Python绑定创建它利用C++26反射机制自动发现类、方法和字段示例:通过单条命令就能将C++中的Vec3类暴露给Python性能测试表明,将热点循环移至C++能带来显著加速Python在简单操作上的开销可能成为瓶颈,这使得C++在计算密集型任务中更具效率C++26反射支持编译时类型检查,从而实现自动绑定生成传统方法如pybind11需要手动列出每个方法和属性Mirror Bridge是优化关键代码段的理想选择,同时保持其余代码库仍使用Python该工具已在GitHub开源,并提供Docker环境便于快速实验
C++ Enum Class and Error Codes, Part 35 months agohttps://mropert.github.io/2025/12/03/enum_class_error_codes_part3/C++错误处理通常需要在每个操作后检查错误,这会使代码变得杂乱。异常提供了一种更清晰的方式,允许函数抛出错误并在其他地方处理它们。异常可以使失败的构造函数更易于管理,无需进行两阶段初始化。关于异常的性能担忧通常基于过时的信息;现代实现已经非常高效。C++中异常的一个主要缺点是函数签名中没有明确记录可能抛出的异常类型。Java的异常处理方式(受检异常与非受检异常)为区分可恢复与不可恢复错误提供了参考模型。与std::expected或错误码等替代方案相比,异常可以使代码更简洁、更易读。C++社区对广泛采用异常的犹豫可能源于历史上的性能误解和编译器缺乏强制规范。
The Cost of a Closure in C5 months agohttps://thephd.dev/the-cost-of-a-closure-in-c-c2y闭包是包含数据和指令的编程结构,与其输入参数或返回值没有直接关联。闭包泛化了函数的概念,使其能够处理未直接传递的实例数据,例如来自外围作用域的变量。除非面向栈或字节码等低级编程环境,否则大多数现代语言都支持闭包。本文重点讨论C和C++中的闭包,旨在为ISO C标准化一种解决方案。C语言中常见的问题是向`qsort`等函数传递额外数据,通常通过静态变量解决,但这存在线程安全和共享状态等局限性。C/C++中的四种主要解决方案包括:使用用户数据指针重新实现函数、GNU嵌套函数、Apple Blocks以及C++ Lambda表达式。性能基准测试显示,C++ Lambda(非类型擦除)速度最快,而GNU嵌套函数和Rosetta Code风格的Lambda由于优化障碍表现不佳。Apple Blocks性能中等,但受ARC开销和复制行为拖累。文章建议,采用轻量级类型擦除层(如`std::function_ref`)可在C闭包的易用性和性能间取得平衡。现有扩展如GNU嵌套函数和Apple Blocks存在实现缺陷,若不改进则不适合直接纳入ISO C标准。
Dependent Names with a Little Encouragement5 months agohttps://consteval.ca/2025/09/27/dependent-names/C++中的依赖名称需要显式语法来消除解析歧义调用依赖成员模板函数时必须使用`template`关键字`typename`关键字用于指明依赖名称引用的是类型新版C++标准在无歧义上下文中允许省略部分注解示例展示了依赖名称若缺乏正确语法会导致解析错误
Loop-Invariant Code Motion5 months agohttps://xania.org/202512/13-licking-licm文章讨论了循环不变代码外移(LICM)优化技术,编译器通过将循环内不变代码移至循环外部来优化性能。示例展示了在每次迭代中调用`vec.size()`的场景,但编译器会将其优化为在循环前仅计算一次。更复杂的案例涉及使用`std::string_view`统计字符范围,编译器将`get_range`调用移出循环。Clang展示了巧妙优化技巧,例如使用`setle`和`setge`指令避免循环内部的分支判断。令人意外的是,GCC未能实现相同优化,可能是由于对`std::pair`等结构化类型的公共子表达式消除(CSE)处理存在问题。文章强调既要信任编译器的优化能力,也应通过Compiler Explorer等工具验证输出结果。本文属于「2025编译器优化探秘」系列,由Matt Godbolt撰写,并经过LLM和人类审阅。
How well do you know C++ auto type deduction?5 months agohttps://www.volatileint.dev/posts/auto-type-deduction-gauntlet/通过多个示例讲解C++中`auto`关键字的类型推导机制基础示例包括从常量、变量和指针推导类型中级示例涵盖引用、CV限定符和数组类型高级主题讨论转发引用、`decltype(auto)`和lambda捕获还涉及结构化绑定和继承场景的类型推导部分无法编译的示例专门展示类型推导的边界情况提供GodBolt在线编译器链接用于验证推导结果鼓励读者通过邮件分享有趣的类型推导案例
A proof of concept of a semistable C++ vector container5 months agohttps://github.com/joaquintides/semistable_vectorsemistable::vector 提供迭代器稳定性,与 std::vector 不同,后者在插入和删除时会失效迭代器。它以连续方式存储元素,并保持与 std::vector 相同的 API,但提供额外的迭代器稳定性保证。该库使用 epoch 描述符跟踪变更,确保迭代器在解引用时正确调整。性能基准测试显示 semistable::vector 操作与 std::vector 相当,使用原始指针可能实现某些优化。线程安全性有限;并发迭代器使用或修改需要采取预防措施。该库为仅头文件形式,依赖 Boost.Config,需要 C++11 或更高版本。未来改进可能包括更好的异常安全性和对未定义迭代器使用的检测。
Map: Operator[] Should Be Nodiscard5 months agohttps://quuxplusone.github.io/blog/2025/12/18/nodiscard-operator-bracket/libc++和微软STL一直在为函数添加[[nodiscard]]属性,但存在例外情况,例如unique_ptr::release函数。map::operator[]在libc++中曾被标记为[[nodiscard]],但由于在Chromium和flatbuffers等代码库中的广泛使用,这一改动被撤销。惯用法'mymap[key];'常用于产生副作用,但这种写法不够清晰,可以用mymap.try_emplace(key)或(void)mymap[key];来替代以提高代码可读性。微软STL和libc++为array、deque和vector的operator[]标记了[[nodiscard]],但考虑到现有使用模式,未对map::operator[]进行标记。LLVM内部容器(如DenseMap、MapVector和StringMap)尚未将operator[]标记为[[nodiscard]],但只需少量修改即可实现。建议:用m.try_emplace(k)或(void)m[k];替代'm[k];'写法,以提升代码清晰度和可维护性。
Aliasing5 months agohttps://xania.org/202512/15-aliasing-in-generalC++中的别名问题可能阻碍编译器优化,特别是同类型指针的情况。使用不同类型(如`int`与`long`)可让编译器通过避免冗余内存更新进行优化。解决别名问题的方法包括使用局部变量进行累加,或采用非标准的`__restrict`关键字。在Rust和Fortran等语言中别名问题较少,这些语言会限制或完全禁止别名行为。
immer – a library of persistent and immutable data structures written in C++5 months agohttps://github.com/arximboldi/immerimmer 是一个 C++ 库,用于持久化和不可变数据结构。它为交互式和并发程序提供了更简单的架构,同时保持高性能。特性包括交互性、并发性、并行性、符合 C++ 习惯的用法以及高性能。该库可定制,并充分利用了 C++14 的特性。安装选项包括手动引入、Nix 包管理器、CMake、vcpkg 和 build2。开发需要额外工具,可通过 Nix 轻松安装,并使用 CMake 生成项目。支持测试和基准测试,结果会保存以供分析。采用 Boost Software License 1.0 许可证授权。
High-performance C++ hash table using grouped SIMD metadata scanning5 months agohttps://github.com/Cranot/grouped-simd-hashtable采用分组SIMD元数据扫描的高性能C++哈希表,在大规模场景下表现优于当前最先进(SOTA)的实现方案与ankerl::unordered_dense的性能对比显示,GroupedSIMD在100万元素规模时开始显现优势,尤其在查询密集型场景中表现突出核心特性包括:SSE2指令集支持、仅头文件实现、针对50万元以上元素表的优化设计该设计借鉴Google瑞士表思想,通过连续内存访问提升SIMD指令效率每个槽位使用1字节元数据标签进行快速过滤,显著提升查询性能采用组间二次跳跃而非线性跳跃,既降低聚集效应又确保所有槽位可达权衡取舍包括插入速度较慢(0.72倍SOTA)且不支持删除和动态扩容该实现源于对Yao猜想的证伪过程,其中分组探测机制是关键突破未来工作将增加删除功能支持,并探索ARM NEON指令集的兼容性
C/C++ Embedded Files (2013)5 months agohttps://www.4rknova.com//blog/2013/01/27/cpp-embedded-files在C/C++程序中嵌入资源文件可以通过外部工具如ImageMagick或xxd实现。ImageMagick可将图像文件转换为头文件,而xxd能处理任意文件类型。使用预处理器是另一种方法,特别适用于着色器等纯ASCII文件,通过将文件内容包裹在宏块中实现。通过汇编代码块可将数据嵌入二进制文件的.rodata节,但这种方法具有平台依赖性。每种方法都有其优势和局限性,例如会增加依赖项或需要修改文件。
Show HN: Hybrid-Transpiler – A tool to convert C++ to Rust and Go5 months agohttps://github.com/cmc-labo/hybrid-transpiler一个将C++代码转换为现代安全语言(如Rust和Go)的源码到源码编译器(转译器),具有高准确性和性能。利用LLVM/Clang完整的C++解析器实现精确的类型系统映射和语义保留。将C++的RAII模式转换为Rust的所有权系统,并将智能指针转换为Rust/Go中的适当形式。支持STL容器转换、模板转泛型,以及将异常处理转换为Rust的Result/Option类型或Go的错误值。包含为Rust和Go生成的FFI接口,允许通过C ABI直接调用C++库。提供C++特性(如线程、协程和虚函数)到Rust和Go对应功能的详细映射方案。提供转译到Rust或Go时不同项目规模的性能指标和执行时间统计。包含完整的转译器项目目录结构,涵盖解析器、中间表示、代码生成和FFI组件。列出当前限制,如对宏展开、复杂模板元编程和内联汇编的支持尚不完善。在MIT许可证下鼓励通过提交错误报告、功能请求和拉取请求进行社区贡献。
Tieredsort: Header only, blazing fast (3-4x) C++17 sorting for numeric types5 months agohttps://github.com/Cranot/tieredsorttieredsort 是一个仅需头文件的 C++17 排序库,针对数值类型进行了优化。在随机数据上比 std::sort 快 3.6 倍,在稠密/少重复数据上快 16-21 倍。能根据数据特征自动选择最佳排序策略。支持 int32_t、uint32_t、int64_t、uint64_t、float 和 double 类型。通过 sort_by_key() 支持对象的稳定排序。无需外部依赖或 SIMD 指令。对 32 位类型有显著加速(3.5-5 倍),对 64 位类型有适度提升(1.4-1.8 倍)。采用三层决策树选择算法:小数据量用 std::sort,稠密范围用计数排序,默认用基数排序。采用 MIT 许可证,欢迎贡献代码。
Time in C++: Inter-Clock Conversions, Epochs, and Durations5 months agohttps://www.sandordargo.com/blog/2025/12/24/clocks-part-5-conversionsC++中不同的时钟类型具有不同的起始时间点和用途,直接比较和转换它们可能会很棘手。C++20引入了`clock_cast`和`clock_time_conversion`,用于在已知关系的时钟之间进行明确定义的转换。对于`system_clock`和`steady_clock`等时钟需要手动关联,但由于可能存在时钟跳变,这种方式容易出错。持续时间转换可能导致精度损失或溢出,因此应使用`floor`、`ceil`或`round`来明确转换意图。最佳实践包括:使用`steady_clock`测量时间间隔、在边界处转换为人类可读格式、避免对时钟关系做假设。
C++ says "We have try at home."5 months agohttps://devblogs.microsoft.com/oldnewthing/20251222-00/?p=111890许多支持异常处理的编程语言都提供'finally'子句,用于在代码块执行后无论是否发生异常都执行特定代码。C++虽然没有'finally'子句,但通过析构函数在离开作用域时执行清理代码。当受保护代码块和'finally'(或析构函数)同时抛出异常时,不同语言表现各异:Java、Python、JavaScript和C#会覆盖原始异常,而C++会终止程序。Python 3.2+版本在'finally'中引发新异常时,会将原始异常保存为上下文信息。C++规定:若析构函数因异常处理而被调用时自身又抛出异常,程序将立即终止。微软WIL库为C++提供了'scope_exit'清理机制,但若清理lambda抛出异常则会终止程序。C++的函数try块可处理构造函数中的异常,但在清理操作方面存在局限性。Python 3.2版本新增了'finally'中的异常链式处理机制,可保留原始异常信息。Java的'getSuppressed'方法处理try-with-resources中的异常,但不适用于'finally'块。C++最佳实践包括使用RAII机制,并避免在析构函数中抛出异常。
The production bug that made me care about undefined behavior5 months agohttps://gaultier.github.io/blog/the_production_bug_that_made_me_care_about_undef...作者讲述了一个C++代码库中的bug:某HTTP接口同时返回'error'和'succeeded'字段为true,而这两个状态本应互斥。问题根源在于结构体中未初始化的布尔字段——由于C++的默认初始化规则,导致了未定义行为。该'Response'结构体因含有非POD类型(std::string),触发编译器生成不初始化原始类型(bool)的默认构造函数。解决方案包括:实现默认构造函数、在结构体定义中设置默认值,或在声明时使用零值初始化(Response response{})。Address Sanitizer(ASan)和clang-tidy等工具能检测此类问题,但需要完备的测试覆盖且存在性能开销。作者对比了C/Go/Rust等语言更简单的初始化方式,凸显C++初始化规则的复杂性与陷阱。文章强调了未定义行为的现实危害:即使代码看似正确,仍可能导致程序出现不可预测的行为。
Why C++ programmers keep growing fast despite competition, safety, and AI5 months agohttps://herbsutter.com/2025/12/30/software-taketh-away-faster-than-hardware-give...C++和Rust是2022至2025年增长最快的主流编程语言,因其在'每瓦性能'和'每晶体管性能'上的高效表现。2025年计算增长的两大制约因素是电力和芯片,其中电力是主要瓶颈。C++26引入了重大安全改进,包括标准库中的边界安全机制,并消除了未初始化局部变量的未定义行为。2022至2025年全球开发者数量增长50%,其中C++和Rust的增速百分比最高。AI是提升生产力的变革性工具,但无法替代熟练的人类程序员,因为解决新问题的需求持续增长。