美文网首页
编译阶段能做什么:属性和静态断言

编译阶段能做什么:属性和静态断言

作者: Drew_MyINTYRE | 来源:发表于2021-06-20 10:54 被阅读0次

    “编译阶段”的目标是生成计算机可识别的机器码。

    编译是预处理之后的阶段,它的输入是(经过预处理的)C++ 源码,输出是二进制可执行文件(也可能是汇编文件、动态库或者静态库)。这个处理动作就是由编译器来执行的。

    有没有用来控制编译器的“编译指令”呢?如果有这么一个东西,让程序员来手动指示编译器这里该如何做、那里该如何做,就有可能会生成更高效的代码。

    到了 C++11,标准委员会终于认识到了“编译指令”的好处,于是就把“民间”用法升级为“官方版本”,起了个正式的名字叫“属性”。你可以把它理解为给变量、函数、类等“贴”上一个编译阶段的“标签”,方便编译器识别处理。
    “属性”没有新增关键字,而是用两对方括号的形式“[[…]]”,方括号的中间就是属性标签,注意属性的编写规范,作用范围。

    [[noreturn]]              // 属性标签
    int func(bool flag)       // 函数绝不会返回任何值
    {
        throw std::runtime_error("XXX");
    }
    
     //  声明变量暂不使用,不是错误
    [[gnu::unused]]     
    int nouse;  
    
     // C++14 or later
    // 当然,程序还是能够正常编译的,但这种强制的警告形式会“提醒”用户旧接口已经被废弃了,应该尽快迁移到新接口。
    [[deprecated("deadline:2020-12-31")]]     
    int old_func();
    

    下面我就列出几个比较有用的(全部属性可参考GCC 文档),GCC 的属性都在 “gnu::” 里。

    • deprecated:与 C++14 相同,但可以用在 C++11 里。

    • unused:用于变量、类型、函数等,表示虽然暂时不用,但最好保留着,因为将来可能会用。

    • constructor:函数会在 main() 函数之前执行,效果有点像是全局对象的构造函数。

    • destructor:函数会在 main() 函数结束之后执行,有点像是全局对象的析构函数。

    • always_inline:要求编译器强制内联函数,作用比 inline 关键字更强。

    • hot:标记“热点”函数,要求编译器更积极地优化。

    静态断言(static_assert)

    static_assert 可以在编译阶段定义各种前置条件,充分利用 C++ 静态类型语言的优势,让编译器执行各种检查,避免把隐患带到运行阶段。

    “静态断言”,static_assert (它是一个关键字),而不是宏。因为它只在编译时生效,运行阶段看不见,所以是“静态”的。它是编译阶段里检测各种条件的“断言”,编译器看到 static_assert 也会计算表达式的值,如果值是 false,就会报错,导致编译失败。

    static_assert(
      sizeof(long) >= 8, "must run on x64");
      
    static_assert(
      sizeof(int)  == 4, "int must be 32bit");
    
    //下面的代码想检查空指针,由于变量只能在运行阶段出现,而在编译阶段不存在,所以静态断言无法处理。
    char* p = nullptr;
    static_assert(p == nullptr, "some error.");  // 错误用法
    

    在泛型编程的时候,怎么检查模板类型呢?比如说,断言是整数而不是浮点数、断言是指针而不是引用、断言类型可拷贝可移动等等?

    想要更好地发挥静态断言的威力,还要配合标准库里的“type_traits”,它提供了对应这些概念的各种编译期“函数”。

    // 假设 T 是一个模板参数,即 template<typename T>
    static_assert(
      is_integral<T>::value, "int");
    
    static_assert(
      is_pointer<T>::value, "ptr");
    
    static_assert(
      is_default_constructible<T>::value, "constructible");
    
    

    相关文章

      网友评论

          本文标题:编译阶段能做什么:属性和静态断言

          本文链接:https://www.haomeiwen.com/subject/lavjyltx.html