首页 > 编程语言 >C++ 静态断言 static_assert

C++ 静态断言 static_assert

时间:2022-09-08 00:56:36浏览次数:97  
标签:断言 静态 C++ assert static 表达式

目录

C++11 引入了静态断言 static_assert,可以在编译期进行断言。

从运行时断言谈起

在静态断言出现前,运行时断言已经存在很久了,我们可以使用 assert(expression) 在运行时进行断言。

运行时断言通常在 Debug 模式下使用而不在 Release 模式下使用(头文件 cassert 通过宏 NDEBUGDebugRelease 版本做了区分),原因很简单,断言失败会显示错误信息并直接中断程序。

注意:断言不能代替程序中的错误检查,它只应该出现在需要断言表达式为 true 的位置,通常用于检查参数或表达式的合法性。如果表达式中涉及到外部输入,则不应该依赖断言。

来看一个例子:

void * resize_buffer(void* buffer, int new_size) {
    assert(buffer != nullptr);	// ok,检查参数合法性
    assert(new_size > 0);	    // ok,检查参数合法性
    assert(new_size <= MAX_BUFFER_SIZE);  // ok,检查参数合法性
    ...
}

bool get_user_input(char c) {
    assert(c == '\0x0d');		// 不合适,断言不应该用于检查外部输入
}

静态断言 static_assert(C++11)

Q:有了运行时断言,为什么需要静态断言捏?

A:运行时断言在运行到断言位置时才触发断言,对于断言表达式是常量表达式的情况,如果可以在编译期就进行检查,能帮助我们提早发现错误,这(在编译阶段断言)正是静态断言所做的。

C++11 引入了 static_assert,它接受两个参数:

  1. 一个常量表达式

    注意,这里需要是常量表达式,也就是不涉及计算,只需要逻辑运算就可以知道结果的表达式。因为 static_assert 作用在编译阶段而不是运行时。

  2. 错误信息

    当断言表达式为 false 时的报错信息。

static_assert 有这些特点:

  • 语法简单:static_assert(expression, error_message);
  • 所有处理在编译期间执行,不允许有空间或时间上的运行时成本,失败的断言会在编译阶段报错
  • 可以在命名空间、类或代码块内使用。
  • 断言失败可以显示丰富的错误诊断信息。

来看一个例子:

#include <type_traits>

class A {
};

class B : public A {
};

class C {
};

template <class T>
class E {
    static_assert(std::is_base_of<A, T>::value, "T is not base of A");  // 判断 T 是否继承自 A
};

int main() {
    static_assert(sizeof(int) >= 4, "sizeof(int) >= 4");
    E<B> b;
    E<C> c;
}

main 函数里包含三个断言:

  • 第一个断言的常量表达式显然为 true,因此不会显示错误诊断信息。
  • 第二个断言判断 B 类型是否继承自 A,也为 true,因此也不会显示错误诊断信息。
  • 第三个断言判断 C 类型是否继承自 A,触发失败断言。

运行结果:

单参数静态断言(C++17)

运行时断言是支持单参数的,C++17 允许 static_assert 接收单参数,即只接收常量表达式作为参数。

还是刚才那个例子:

#include <type_traits>

class A {
};

class B : public A {
};

class C {
};

template <class T>
class E {
    static_assert(std::is_base_of<A, T>::value);  // 判断 T 是否继承自 A
};

int main() {
    static_assert(sizeof(int) >= 4);
    E<B> b;
    E<C> c;
}

运行结果:

static_assert 使用场景

相比运行时断言,静态断言可以将错误排查提前到编译阶段。因此,当断言表达式是常量表达式时,我们应该优先使用静态断言 static_assert

参考资料

  1. 现代C++语言核心特性解析

标签:断言,静态,C++,assert,static,表达式
From: https://www.cnblogs.com/linrj/p/16667831.html

相关文章

  • C++ 关于构造函数和this调用的思考
    文中一系列思考和内容引发自以下问题:我需要在一个类的构造函数中调用另一个对象的构造函数,并使用this初始化其中的一个引用成员。主要遇到的问题:1.构造函数的初始化列表......
  • AC C++ 1.6函数
    1、C++中,int返回值的函数可以写return,不会报错,但是返回值会是一个随机值2、函数定义与函数声明,声明不需要写函数体,形参名也可以没,只有一个形参类型就行。声明和定义前后顺......
  • C++中构造函数的超详细讲解
    转:https://blog.csdn.net/guishangppy/article/details/125876729C++在C语言的基础上增加了类和对象的概念,官方对类和对象的解释是:对象是类的实例化,类是对象的抽象,其实这......
  • 使用c++ librados库操作ceph pool
    centos需要安装依赖:yuminstalllibrados2代码如下://代码中使用到的部分参数://cluster_name(默认为ceph)//user_name(默认为client.admin)//con......
  • C++ 由快排学习到的的随机数等知识
    起:力扣的912题数组排序,想着先用快速排序来写写,在实际用c++编写的时候,有一些之前没注意到的细节问题造成了一些麻烦。912.排序数组-力扣(LeetCode)   快排......
  • ACM模式各种输入总结 C++
    一、整型数组输入:(很简单)在终端的一行中输入固定数目的整型数字,并存到数组中,中间以空格分隔。示例:3123intn;cin>>n;vector<int>nums(n);......
  • vscode环境配置(C/C++)
    一.MinGW和vscode的简单了解1.MinGW是什么?MinGW(MinimalistGNUonWindows)。它实际上是将经典的开源C语言编译器GCC移植到了Windows下,并且包含了Win32API,因此可......
  • c++知识点速刷
    语法指针和引用指针:存放某个对象的地址引用:变量的别名,从一而终,不可变,必须初始化const变量指针常量(底层const):指针所指的对象不可变常量指针(顶层const):指针不可变defin......
  • 强化学习——价值迭代算法 悬崖漫步为例 C++
    #include<bits/stdc++.h>usingnamespacestd;#defineN100#definecliffcliff_mapintrow,col;structState{intnext_i,next_j,flag;doublereward;......
  • vc++ get random via random_device,mt19937
     #include<ctime>#include<iostream>#include<random>usingnamespacestd;staticrandom_devicerd;staticmt19937mt{rd()};template<typenameT>vo......