跟我学C++中级篇—编译期检查

C++26反射如何让借用检查在编译期落地 内存安全是C++工程长期关注的核心议题。传统依赖AddressSanitizer等运行时工具,问题往往在线上才暴露。借鉴Rust的所有权与借用规则,C++社区尝试将生命周期约束前置到编译期。通过类型系统编码、静态分析以及C++26反射提供的编译期类型结构洞察,开发者能够更早发现悬垂指针与数据竞争风险。这类方案尤其适合多线程共享状态、核心基础设施等场景,用编译器诊断替代深夜调试,提升长期可维护性。 阅读详情

一、代码检查

在前面的文章中,已经对代码的管理从开始编写到最后提交甚至部署都有了较为详细的说明分析。特别对代码在编译期的检查进行过多个角度的分析说明。为了让大家对编译期检查有一个全面的理解,本文将对编译期时的检查进行一个综合的分析说明。

二、分析

正如人们理解疾病以预防为主一样,代码开发也要从最初级的源头来进行控制。代码的安全检查,虽然可以辅以人工和各种工具,但在编译期的检查仍然是最主要的一环。在编译期对代码进行控制,可以显示的处理下面的各类问题:

  1. 数据类型问题
    这是编译器对代码检查的基础控制,C++是一种强类型的语言,如果数据本身都无法通过检查,其它也没有意义了。它包括类型大小、对齐、转换以及模板参数的属性等检查。另外,在继承中的多态类型处理检查也是重要的一种情况
  2. 语法问题
    这也是基础的检查,对一些基础的语法的应用是否正确,是否缺少分号、括号是否匹配、关键字是否错误等等进行基础的检查。还包括对常量和边界的控制检查等等
  3. 逻辑问题
    随着编译期功能的愈发强大,新的C++标准提供了各种编译器处理的逻辑方式如if constexpr等,包括早期的SFINAE技术等,编译期都需要对其进行检查
  4. 条件验证问题
    这种就更多了,比如值的正确性检查、结果验证等等。常见的如static_assert以及原来一些各平台自带的类似的判断宏等
  5. 接口问题
    接口问题之所以单独拿出来,主要原因在于接口更强调的是约束。所以语法的约束是一个强检查,当然也包括前面的语法和数据类型等检查。最典型的是C++20推出的Concepts检查
  6. 环境与依赖问题
    这个就属于经典的编译期检查处理,当然也包括了链接时的检查。相当常见,如各种库的路径、版本以及机器位数等的显式的检查

编译期的检查作用非常大,它可以将问题及时暴露出来,防止把错误引入到运行时,造成严重的破坏。一般来说,编译期检查的作用主要有:

  1. 保证类型的安全性:这是强类型语言的基础要求
  2. 对语法规则的检查和相关约束机制的控制:比如基础的语法的逻辑判断、转换控制以及各种约束条件和分支管理等等
  3. 预防大于治疗:把错误尽量消灭在编译期,而不引入运行时导致各种异常甚至崩溃,降低调试和维护成本
  4. 无运行时成本:相关的错误检查都在编译期完成,不会造成运行时的效率的降低

三、编译期检查的分类

在编译期进行检查,一般可以分为以下几类:

  1. 预处理
    这个是贯穿早期和现代C++编程的重要基础检查机制。主要针对头文件依赖、编译器特性及平台检测以及错误处理和辅助支持等。它的优点在于编译的早期检查和环境依赖处理;缺点是功能很基础,类型检测不太可靠且有可能穿越命名空间导致污染
  2. 静态处理
    这里包括早期的通过宏和模板等实现的检查机制,也包括C++11标准后的静态断言static_assert()以及constexpr与consteval等新关键字处理。主要用于编译期验证条件和强制编译期运行。
    它的优点在于计算前移提升了性能,但缺点是会要求常量表达式处理、降低了编译效率并可能占用更多的内存
  3. 类型萃取和元编程
    这在模板编程和元编程中应用非常多,通过Type Traits进行类型推导和逻辑判断。它的优点在于非常灵活、功能强大而且C++标准和库都有相当完全的支持。缺点也非常明显,学习成本太高,另外也增加了编译的时间
  4. SFINAE处理
    SFINAE技术是模板元编程中的一个重要的技术点,通过和std::enable_if配合使用,可以实现模板的逻辑处理及相关错误处理。优点是灵活、可扩展;缺点是代码可维护性差、错误信息不容易理解,出现问题也难于调试
  5. 编译分支处理
    这是C++17后引入的编译条件分支处理,它对未实例化分支不作检查。优点是代码可维护程度高、逻辑清晰。由于未实现分支不处理一定程度上减少了代码膨胀;缺点是标准要求必须在C++17以上,而且需要配合Type Traits一起使用。无法在函数外使用并要求条件必须是常量表达式
  6. 概念约束
    Concepts其实主是一种精简版的SFINAE,加强了对模板使用的约束性检查。其优点在于语法简洁、错误明确、代码易维护。缺点是标准要求更高C++20以上,同时学习成本仍然存在

编译期检查其实可以理解为由开发者替机器来考虑如何对代码进行控制。所以就需要开发者对机器的运行有一定的了解,这样才能更好的对编译期进行的各种分支判断、逻辑处理和类型检查、转换等有较强的理解,从而开发中更高效、简单可维护的代码。

四、例子

其实编译期检查的相关的例程在前面写了很多,下面综合一下再给出一个,供参考:

//SFINAE例子--MUDUO中的例子
#include <iostream>
namespace detail
{
template<typename T>
struct has_no_destroy
{
  template <typename C> static char test(decltype(&C::no_destroy));
  template <typename C> static int32_t test(...);
  const static bool value = sizeof(test<T>(0)) == 1;
};
}  // namespace detail
template <typename T>
 static void init(T t)
  {
    T* value_ = new T();
    if (!detail::has_no_destroy<T>::value)
    {
            std::cout<<"is ok"<<t<<std::endl;
      //::atexit(destroy);
    }
  }

int main()
{
    int num = 200;
    init<int>(num);
    return 0;
}

//C++11后
template<typename T>
auto len (T const&& t) -> decltype((void)(t.size()) , T::size_type)//也可以使用std::enable_if,修改一下表达式即可
{
    return t.size();
}
//C++20
template<typename T>
concept func_ask = requires(T t)
{
    t.no_destroy();
};

通过对比很容易可以发现相关的技术演进导致的代码编写的安全性和可维护性的提高。其它如静态检查和萃取等在前面都有专门描述,不再一一的给出具体的例程,有兴趣可以搜索前面的相关文章即可。

五、总结

编译期检查是一种重要的代码安全机制。但正如反复说过的一句话”任何事物都具有两面性“。不能把所有的解决问题的思路都放到编译期,一是其能力无法满足检查只有在运行期才会出现的问题,另外一个就是过多的编译期检查,对于大的项目来说,编译期成本也是相当高的。所以,还是要根据实际情况来确定如何正确的使用编译期检查机制。推荐的原则是:高频的计算较少的使用编译期检查,而低频计算量较大的使用运行时检查。

C++编译期借用检查:用反射和静态分析拦截内存安全问题 内存安全是C++工程长期面临的挑战,悬垂引用、迭代器失效和数据竞争等问题往往要等到运行时才暴露。编译期静态分析技术兴起后,开发者开始尝试将Rust的所有权与借用模型引入C++,在构建阶段自动识别危险操作。C++26反射能力为这类工具注入了新活力,它让编译器获取类型成员信息,结合模板元编程和Clang插件,可以实现更智能的生命周期约束与可变别名检测。该方案适合底层库、游戏引擎、嵌入式及安全关键系统,无需改写存量代码即可降低内存事故率。文章梳理了从模板库到LibTooling插件再到反射辅助的实现路线,并给出构 阅读详情

相关推荐

C++编译期的类型测试

编译期的类型测试 一、使用模板特化机制 如比较两个类型是否一致: VC8及以后版本支持了type traits机制: add_const Class            // Makes const type from type. add_cv Class               // Makes const/volatile type from type.

在水一方 2313

跟我学C++中级篇——宏与constexpr

本文对比了C++中宏与constexpr的差异:宏仅进行文本替换,不进行类型检查且作用域不受限,适用于预处理和条件编译;constexpr则进行强类型检查,受作用域限制,支持编译期计算和复杂操作,调试更友好。虽然constexpr在大多数场景下更优,但宏在条件编译等特殊场景仍有优势。开发者应根据具体需求选择合适方案,权衡可维护性与功能需求。

fpcc的专栏 607

C++类型安全ORM:sqlpp11编译期检查与MySQL实战指南

在数据库操作中,ORM(对象关系映射)框架通过将数据库表映射为编程语言中的类,简化了数据访问层的开发,提升了代码的可维护性。其核心原理在于抽象SQL操作,让开发者以面向对象的方式处理数据,从而减少直接拼接SQL字符串带来的安全风险与错误。从技术价值看,类型安全的ORM能在编译阶段捕获SQL语法和类型错误,显著提升代码的健壮性。尤其在C++这类缺乏运行时反射的语言中,利用编译期元编程实现类型安全显得尤为重要。应用场景广泛覆盖后端服务、金融系统等对数据一致性要求高的领域。sqlpp11作为C++中类型安全ORM

weixin_30736301的博客 336

跟我学C++中级篇—static_assert和assert

对c++中的编译期断言和运行时断言进行分析说明

fpcc的专栏 501

CH32V IAP跳转避坑指南:为什么你的APP跳不过去?从mstatus寄存器配置到函数属性详解

本文深入解析CH32V系列MCU的IAP跳转机制,从mstatus寄存器配置到函数属性优化,详细讲解如何避免APP跳转失败。文章涵盖地址准备、模式切换、跳转执行等关键步骤,并提供调试技巧与实战案例,帮助开发者快速解决CH32V IAP跳转中的常见问题。

weixin_30955617的博客 140

【可信数据空间-部署方案】

此部署架构体现了以下几个核心原则:去中心化: 数据存储和处理完全分布在各个参与者端,运营方只提供核心的协调和信任基础设施。安全边界清晰: 通过VPC、DMZ、防火墙、K8s命名空间等技术,在每个层级都建立了严格的安全边界。高可用与弹性: 所有关键服务均以集群方式部署,避免单点故障,并能根据负载动态伸缩。云原生: 全面采用容器化和Kubernetes编排,简化部署、管理和运维复杂度。合规性: 架构设计天然满足数据驻留要求(数据留在企业本地),并为所有操作提供不可篡改的审计追踪能力。

u014716614的博客 771

跟我学c++中级篇——再谈Concepts

重新认识一下Concepts这个c++20中提出的概念

fpcc的专栏 1655

RV1126B芯片实战:如何用这款视觉处理器SoC打造你的第一个AI摄像头项目

本文详细介绍了如何利用瑞芯微RV1126B视觉处理器SoC从零构建AI摄像头项目。涵盖硬件选型、开发环境搭建、ISP配置、AI模型部署及系统集成等关键步骤,帮助开发者高效实现边缘计算方案,特别适合智能安防和工业检测应用。

dropout6artist的博客 931

跟我学C++中级篇——C++17中的std::void_t

std::void_t更好的是在模板和元编程中应用,这也是C++的一个发展的重点。毕竟泛型编程是每个语言都不能舍弃的情怀。所以对大多数程序员来说,std::void_t这个元函数属于一种应用非常少的情况。可以先了解一下,然后再真正遇到后再认真学习。在这篇普及的文章基础上,后面将对enable_if与std::void_t以及C++20中的std::integral‌进行一次系统的分析说明。这样,会让大家能从整体到细节上对模板和元编程中的相关用法有一个清晰的认识。

fpcc的专栏 1113

STM32F407+LWIP实战:手把手教你移植mbedtls库实现Modbus TCP双向认证

本文详细介绍了如何在STM32F407微控制器上移植mbedtls库,结合LWIP协议栈实现Modbus TCP的双向认证功能。通过TLS 1.2加密通道,有效提升工业物联网通信的数据安全性,涵盖证书管理、内存优化及性能调优等关键步骤,为嵌入式系统开发者提供了一套完整的解决方案。

weixin_28721917的博客 516

GPU硬件架构与微架构深度解析28-稀疏计算:稀疏矩阵计算的硬件支持

本文介绍了GPU加速稀疏计算的关键技术。主要内容包括:1)稀疏数据的存储格式(COO、CSR、CSC)及其特点;2)现代GPU的稀疏计算硬件优化,如NVIDIA的稀疏张量核心和内存访问优化;3)稀疏计算在推荐系统、NLP和科学计算等领域的应用案例;4)性能优化技巧,包括存储格式选择、硬件特性利用和混合精度计算等。文章指出,专用稀疏计算技术可显著提升AI和大规模科学计算的效率,相比传统方法可获得5-10倍的性能提升。

2301_79143213的博客 114

跟我学C++中级篇——std::is_invocable的分析应用

本文介绍了C++17标准中的std::is_invocable系列接口,用于在编译时检查函数调用的安全性。文章首先阐述了该特性的背景和重要性,指出它能有效防范模板编程中的运行时错误。随后详细解析了其定义和实现原理,包括四种主要接口(基础调用检查、返回值检查及对应的异常安全版本)及其辅助函数。技术分析部分揭示了这些接口仍基于SFINAE技术,通过decltype和declval实现参数和返回类型检测。文章还列举了该特性的主要应用场景(模板元编程、函数签名检查等)和使用限制,最后通过示例代码演示了如何检查成员函

fpcc的专栏 823

【Unity】RPG2D龙城纷争(十九)流程与UI界面(终章)

本章为RPG2D系列的终章,在之前的章节中我们已经完成了游戏的所有基本功能,那么用流程与UI界面将其串联起来才是我们整个游戏原型完善的标志。

神码编程 917

C++静态断言与编译期检查的高级应用

C++11引入的static_assert将断言机制提升至编译期,通过模板元编程与类型系统结合,实现了零开销的错误预防。现代C++20的consteval和concept进一步强化了编译期能力,静态断言正从辅助工具演变为类型系统的核心组件。结合模块化(C++20)和反射提案(C++23),未来将实现更精细的编译期契约管理。语法结构:static_assert(condition, message)要求condition为编译期常量表达式,失败时直接终止编译并显示message。引言:编译期检查的范式革命。

2501_93395246的博客 770

【并发编程五】c++进程通信——共享内存(shared memmory)

现代操作系统,对于内存管理,采⽤的是虚拟内存技术,也就是每个进程都有⾃⼰独⽴的虚拟内存空间,不同进程的虚拟内存映射到不同的物理内存中。所以,即使进程 A中 和 进程 B中 的虚拟地址是⼀样的,其实访问的是不同的物理内存地址,对于数据的增删查改互不影响。这样这个进程写⼊的东⻄,另外⼀个进程⻢上就能看到了,都不需要拷⻉来拷⻉去,传来传去,⼤⼤提⾼了进程间通信的速度。⽤了共享内存通信⽅式,带来新的问题,那就是如果多个进程同时修改同⼀个共享内存,很有可能就冲突了。那共享内存的⽅式,就很好的解决了这⼀问题。

junxuezheng的博客 1万+

【数字孪生与仿真技术】05:从原理到实战:MATLAB/Simulink在航空航天GNC系统开发中的深度解析(含全流程代码与认证指南)

摘要:本文系统阐述MATLAB/Simulink在航空航天制导、导航与控制(GNC)系统开发中的核心应用。通过解析GNC系统高保真动力学建模、多源导航传感器融合、鲁棒控制算法设计等关键技术原理,结合Virgin Orbit运载火箭、CubeSat等真实案例,展示从需求分析、模型搭建、仿真验证到代码生成与认证的完整开发流程。文中提供1200余行关键代码、8个可复用Simulink模型及详细执行结果展示,涵盖DO-178C认证支持、实时性能优化等工业级开发规范,为航空航天工程师、科研人员提供可落地的参考方案。

专注于人工智能、软件开发、工控自动化、工厂数字化及智能化等领域,希望和大家共同进步! 1657

跟我学C++中级篇——Concepts的循环依赖

本文探讨了C++20概念(Concepts)中可能出现的循环依赖问题。文章指出,循环依赖在复杂模板编程中可能出现,表现为多个概念间的相互约束,类似于数学定理间的循环证明。通过示例代码展示了概念A依赖B、B又依赖A的典型循环场景。为解决这一问题,提出了三种设计方法:高层抽象、减少互相约束、分解复杂概念;以及两种编程技巧:使用前向声明和延迟加载约束检查。最后强调良好的设计思想是避免概念循环依赖的关键,编程技巧只是辅助手段。全文为处理C++概念循环依赖提供了实用指导。

fpcc的专栏 543

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C++ 编译期检查返回值是否被使用

为了处理错误,可以把函数的返回值定为bool 或 int 或 自定义的result,调用程序时约定检查返回值来判断程序是否出现异常;C++ 中的 [[nodiscard]] 是 C++17 引入的一个属性(Attribute),用于提示开发者或编译器:​。如此声明函数,编译期发现在critical_operation函数调用的返回值被忽略时会发出警告。当使用这个选项时,对所有函数的返回值被忽略时都会发出警告。这里就需要一种编译期的检查提示必须使用函数的返回值.上面例子在编译时会出现警告。

weixin_43868793的博客 525

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

CPP-Summit-2022 学习:C++编译期编程的过去、现在和未来

编译期编程 vs 运行期编程 解释: 解释:https://godbolt.org/z/ohjM8EqKM https://godbolt.org/z/PjdMede9z 解释:公式示意:编译期编程(Compile-Time Programming),指的是尽量在编译阶段就完成计算、类型检查、模板实例化等操作,而不是在运行时才去做。 在 C++ 中,主要体现为: 提高类型安全性 编译期编程可以在编译阶段检查类型是否合法,而不是运行时才报错。 减少运行时开销 通过模板和 可以避免运行时分支和计算。

虾球 973

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

跟我学C++中级篇—强制类型转换

本文分析了C++中的四种强制类型转换机制:static_cast(基础类型转换、向上转型)、const_cast(CV限定符处理)、dynamic_cast(运行时安全类型检查)和reinterpret_cast(低层危险转换)。通过对比传统C语言强制转换,阐述了C++引入更安全转换机制的必要性,并提供了各类转换的代码示例。文章指出C++类型转换的发展趋势是更安全、更精细化的类型控制,但为保持灵活性仍需兼容多种转换方式,这也是C++复杂性的体现。最后强调没有普适的转换方案,需根据具体场景选择合适方式。

fpcc的专栏 432

C++编译期类型检查原理与实践指南

类型安全是编程语言的核心机制,通过编译期类型检查可以在代码转换为机器指令前捕获类型错误。其原理基于类型系统和模板元编程,利用static_assert、SFINAE和类型萃取等技术,在编译阶段验证类型约束。这种技术能有效预防隐式转换错误和类型滥用,特别适用于金融计算、跨模块接口等对类型敏感的场景。现代C++通过Type Anchoring和Concepts等特性,实现了零开销的类型安全方案。在实际工程中,结合类型锚定技术和编译期断言,可以构建强类型接口,避免类似财务精度误差或危险指针转换等问题。

weixin_34405557的博客 409

C++11断言static_assert(静态断言,编译期检查)

在上面的代码中,is_power_of_two结构体使用static_assert检查模板参数N是否大于0,并检查N是否为2的幂次方。在main函数中,定义一个大小为8的数组,并使用is_power_of_two结构体检查数组大小是否为2的幂次方。与assert不同的是,static_assert是在编译期进行检查,而不是在运行期进行检查。在上面的代码中,print函数使用static_assert检查模板参数T是否为整数类型,如果不满足则编译器会报错并输出错误信息。表示N是否为2的幂次方。

Dontla的博客 2050

C++编译期反射简介

一、什么是C++编译期反射?1、介绍2、特性与用途3、常见实现方式二、C++编译期反射的案例1、自动生成序列化/反序列化代码2、验证类型约束(Type Constraints)3、枚举类型的编译期反射4、自动生成类的访问器(Getters/Setters)5、模板化代码生成总结今天听到一个新词语:C++编译期反射,给我整蒙了,毕业从事C++软件开发一年了,居然都没听说过,有点羞愧难当,于是去网上搜索学习了一番C++编译期反射。

qq_45797625的博客 1389

跟我学C++中级篇——数据类型转换的思考

从上面的分析其实可以明白,就是开发者不能简单的相信自己或其它开发者的技术,要善于借助编译器等工具进行安全检查即开发的数据类型转换代码可以由编译器进行类型判别,防止出现异常。要尽量使用显示的数据类型转换,而不是使用不可控的隐式数据类型转换。阳光透明才安全,安全永远是第一位的,这个是常识!

fpcc的专栏 1033

UTF8-CPP跨版本兼容性指南:从C++98到C++20的完整支持

UTF8-CPP是一个轻量级的C++库,专注于以可移植的方式提供UTF-8编码和解码功能,支持从C++98到C++20的全版本C++标准。无论是处理多语言文本还是确保跨平台字符编码一致性,这个库都能为开发者提供可靠的解决方案。 ## 为什么选择UTF8-CPP? 在C++开发中,字符编码处理常常是跨平台项目的痛点。UTF8-CPP通过模块化设计,为不同C++标准提供针对性实现,确保代码在各种编

gitblog_01046的博客 932

用C++模板元编程实现编译期借用检查:从Rust借鉴的工程实践

内存安全是系统级编程长期关注的焦点,Rust通过所有权与借用机制在编译期拦截悬垂指针和数据竞争等风险,而C++开发者往往依赖运行时智能指针和静态分析工具兜底。模板元编程提供了一种在编译期操作类型与状态的能力,配合static_assert可以构建轻量级的类型状态机,将资源生命周期和访问规则编码为类型约束。通过借用模式标记、生命周期索引和所有权转移模拟,开发者可以提前捕获非法访问,减少运行时崩溃。这一思路特别适用于资源句柄管理、初始化时序控制和高并发场景下的访问约束。C++26反射的演进将进一步提升编译期检查

weixin_33796177的博客 606
上一篇: 并行编程实战—CUDA中的Tile编程之三Tile空间加载与存储
下一篇: 跟我学C++中级篇——编译期的条件选择
fpcc
fpcc 新星创作者: C/C++技术领域 新星创作者: C/C++技术领域
博客等级 码龄22年 4040粉丝 1189原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值