• C++ 静态断言 static_assert


    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');		// 不合适,断言不应该用于检查外部输入
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    静态断言 static_assert(C++11)

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

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

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

    1. 一个常量表达式

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

    2. 错误信息

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

    static_assert 有这些特点:

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

    来看一个例子:

    #include 
    
    class A {
    };
    
    class B : public A {
    };
    
    class C {
    };
    
    template 
    class E {
        static_assert(std::is_base_of::value, "T is not base of A");  // 判断 T 是否继承自 A
    };
    
    int main() {
        static_assert(sizeof(int) >= 4, "sizeof(int) >= 4");
        E b;
        E c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    main 函数里包含三个断言:

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

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ourh9qX8-1662568283943)(C:\Users\Lin\AppData\Roaming\Typora\typora-user-images\image-20220908002222169.png)]

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

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

    还是刚才那个例子:

    #include 
    
    class A {
    };
    
    class B : public A {
    };
    
    class C {
    };
    
    template 
    class E {
        static_assert(std::is_base_of::value);  // 判断 T 是否继承自 A
    };
    
    int main() {
        static_assert(sizeof(int) >= 4);
        E b;
        E c;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    运行结果:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-W6eejuQ0-1662568283944)(C:\Users\Lin\AppData\Roaming\Typora\typora-user-images\image-20220908002733243.png)]

    static_assert 使用场景

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

    参考资料

    1. 现代C++语言核心特性解析
  • 相关阅读:
    vue-cli3 vue项目 动态修改favicon.ico(浏览器顶部小图标)
    云上有AI,让地球科学研究更省力
    我注册了某音帐号之后。。。(内含推荐算法)
    数组与list的转化分析
    Cerebral Cortex:从任务态和静息态脑功能连接预测儿童数学技能
    嵌入式开发中模板方法模式实现
    设计模式-建造者模式
    Django中的事务
    快速挖掘设备逻辑洞方法分享
    一文讲透 “中间层” 思想
  • 原文地址:https://blog.csdn.net/RJ_theMag/article/details/126756572