首页 > 编程语言 >C++断言之assert和static_assert的区别

C++断言之assert和static_assert的区别

时间:2023-10-06 10:24:46浏览次数:42  
标签:断言 C++ assert 编译 static sizeof 表达式

C++断言之assert和static_assert的区别

参考链接:c++11:static_assert 与assert_夜夜夜夜-CSDN博客_static_assert

断言分为动态断言和静态断言2种。c++11引入了static_assert关键字,用来实现编译期间的断言,叫静态断言。

1.static_assert 静态断言

static_assert(常量表达式,要提示的字符串);

如果第一个参数常量表达式的值为false,会产生一条编译错误,错误位置就是该static_assert语句所在行,第二个参数就是错误提示字符串。然后通过调用 abort 来终止程序运行。_

使用static_assert优点:

  1. 可以在编译期间发现更多的错误,用编译器来强制保证一些契约,并帮助我们改善编译信息的可读性,尤其是用于模板的时候

  2. static_assert可以用在全局作用域中,命名空间中,类作用域中,函数作用域中,几乎可以不受限制的使用。

  3. 编译器在遇到一个static_assert语句时,通常立刻将其第一个参数作为常量表达式进行演算,但如果该常量表达式依赖于某些模板参数,则延迟到模板实例化时再进行演算,这就让检查模板参数成为了可能。

  4. 性能方面,由于是static_assert编译期间断言,在编译时进行处理,不生成目标代码,因此static_assert不会造成任何运行期性能损失,这就使得它比assert宏具有更好的效率。

示例

1.static_assert(sizeof(void *) == 4, "64位系统上不支持")

该static_assert用来确保编译仅在32位的平台上进行,不支持64位的平台,该语句可以放在文件的开头处,这样可以尽早检查,以节省失败情况下的编译时间。

2.模板函数使用静态断言static_assert在编译期识别模板实例化错误

#include <cassert>
#include <cstring>
using namespace std;

template <typename T, typename U> int bit_copy(T& a, U& b){
    assert(sizeof(b) == sizeof(a));
  //static_assert(sizeof(b) == sizeof(a), "template parameter size no equal!");
    memcpy(&a,&b,sizeof(b));
};

int main()
{
    int aaa = 0x2468;
    double bbb;
    bit_copy(aaa, bbb);
    getchar();
    return 0;
}

这里使用assert运行时断言,但如果bit_copy不被调用,我们将无法触发该断言,实际上正确产生断言的时机应该在模版实例化时,即编译时期。使用static_assert替换assert再次编译,即可获得一个错误并显示我们指定的错误信息。

注意:static_assert的断言表达式的结果必须是在编译时期可以计算的表达式,即必须是常量表达式。如果使用变量,则会导致错误。

2.assert 动态断言

assert是运行期断言,它是一个宏,用来发现运行期间的错误,不能提前到编译期发现错误,也不具有强制性,也谈不上改善编译信息的可读性,既然是运行期检查,对性能当然是有影响的,所以经常在发行版本中,assert都会被关掉;

void assert(int expression);

assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行

由于assert是运行期的判断,并且会强制终止程序,一般要求只能用于debug版本中,是为了尽可能快的发现问题。assert是要从release版本中去掉。所以一般开发会重新定义assert宏。

3.#error 预编译期断言

#error可看做预编译期断言,甚至都算不上断言,仅仅能在预编译时显示一个错误信息,它能做的不多,可以配合#ifdef/ifndef参与预编译的条件检查,由于它无法获得编译信息,当然就做不了更进一步分析了。

#ifndef __GNUC__ // 没有定义 __GNUC__ 宏,表示使用的不是gcc编译器
#error 代码中使用了 gcc 特有的扩展,必须使用 gcc 编译器编译 //这里就是要显示给用户的错误信息
#endif

标签:断言,C++,assert,编译,static,sizeof,表达式
From: https://www.cnblogs.com/3to4/p/17744282.html

相关文章

  • C++ 信号
    信号概念信号是Linux进程间通信的一种机制,是软件层次上对中断的一种模拟,用在进程之间的传递消息。来源内核产生内存错误,除0错误等由其他进程产生,传递给目标进程kill信号自定义信号:SIGURG硬件产生键盘处理方式发送阶段内核将信号放到对应的pendi......
  • C++算法之旅、08 基础篇 | 质数、约数
    质数在>1的整数中,如果只包含1和本身这两个约数,就被称为质数(素数)866试除法判定866.试除法判定质数-AcWing题库\(O(n)\)boolisprime(intx){if(x<2)returnfalse;for(inti=2;i<x;i++)if(x%i==0)returnfalse;returntrue;......
  • 14_C++对c的扩展
    c++对c的扩展::作用域运算符::使用全局变量usingnamespacestd;inta=10;voidtest01(){inta=20;cout<<a<<endl;//20cout<<::a<<endl;//10}命名空间namespacenamespace和c语言中static只在本源文件中有效差不多命名空间使用语法创建一......
  • C++ 数据结构插入效率学习
    转自:https://blog.csdn.net/breaksoftware/article/details/829478381.总结在头部插入。元素数量>15k时,效率unordered_set>set,unordered_map>map。元素数量<1024时,效率unordered_set>set,map> unordered_map。元素数量<256时,效率unordered_set>set,map> unorder......
  • C++ namespace User_Unauthorized version 1.0.0 is officially released
    CodenamespaceUser_Unauthorized{/***@briefThisisaheaderfileforcompetitiveprogramming.*@authorUser-Unauthorized*@version1.0.0*@date2023-10-5*/typedeflonglongvalueType;typedefstd::vector<......
  • C++ Profiler Introduction [CPU Time Only]
    C++ProfilerIntroduction[CPUTimeOnly]author:LastWhisperdate:2023/10/05ThereareseveralprofilersforC++.Basedonmyresearch,I'vefoundthattracyisthemostpowerful.However,it'schallengingtoconfigure.Toquicklybenchmark......
  • C/C++学习 -- HMAC算法
    1.HMAC算法概述HMAC,全称为HMAC-MD5、HMAC-SHA1、HMAC-SHA256等,是一种在数据传输中验证完整性和认证来源的方法。它结合了哈希函数和密钥,通过在数据上应用哈希函数,生成一个带密钥的散列值,用于验证数据的完整性。HMAC算法广泛应用于网络协议、数字签名、认证和访问控制等领域。2.HM......
  • 用C++写的一个万用哈希函数模板
    用C++写的一个万用哈希函数模板template<typenameT>inlinevoidhash_combine(size_t&seed,constT&val){seed^=hash<T>()(val)+0x9e3779b9+(seed<<6)+(seed<<2);}template<typenameT,typename......
  • windows上的C++编译环境
    Windows上的C++编程环境比Linux上的繁杂很多,有许多工具已经很老了,但是很多教材也还在用,很多学校的教学也还在用。另一方面,有更现代的选择,但是需要一些必要的配置和对工具链组成的理解,本文将必要的环境都介绍一遍,让新手能有一个相对完整的理解,然后迅速抛弃老旧的工具链,使用更现代......
  • VC++编写ActiveX控件方法
    暑假在做一个项目的时候,本来是用C#.NET来写的一个港口进出闸的流程控制程序,里面涉及一个响应用PLC的采集信息的问题(PLC用串口和工控机相连接),然后思考如何用C#写串口通讯程序,结果师兄在一旁直接用VC++写了一个“*.ocx控件”,并在自己的电脑上进行了测试,完工后就把生成的“*.ocx”控......