• c++ noexcept与constexpr解析


    1. noexcept无需抛出异常

    在C++中使用noexcept来标识一个函数不会抛出异常。

    noexcept:noexcept默认为true的形式,即抛出异常。

    void f() noexcept; // 不会抛出异常
    void (*fp)() noexcept(false); //false,抛出异常
    
    • 1
    • 2

    要尽量使用noexcept而不是throw。

    throw抛出异常:

    int m_div(int a,int b)throw(...)	//throw表示接收任何类型的异常
    {
        if (b==0)
        {
            throw(1);	//除数为零,则操作非法,抛出异常
        }
    	return a/b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    noexcept抛出异常:

    int m_div(int a,int b)noexcept(false) //允许抛出异常 
    {
        if (b==0)
        {
            throw(1);	//除数为零,则操作非法,抛出异常
        }
    	return a/b;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2. constexpr静态编译关键字

    constexpr所表示的是它所声明的变量或者函数,都在静态编译时就已经完成。

    程序的运行过程: 编译 ---- 链接 ---- 执行

    使用constexpr表示在编译阶段编译器就已经知道了这个变量或者函数的值。

    编译期常量

    在我们定义数组的时候:给一个变量当作数组的大小是错误的,因为这是一个变量,不是一个常量表达式,数组只接收常量表达式作为初始大小。

    int arr1[5]={1,2,3,4,5}; //ok
    int a=10;
    int arr2[a]={1,2,3....}	 //error
    
    • 1
    • 2
    • 3

    使用constexpr:constexpr修饰此变量为一个常量表达式,即a在编译时就已经确定了,因此他是一个编译期常量,可以当作数组的大小。

    constexpr int a=10;
    int arr[a]={1,2,3,4,5....}	//ok !
    
    • 1
    • 2

    从函数返回常量表达式:返回值是一个常量表达式,可以用作指定数组的大小。

    constexpr int func(int a)
    {
    	return 1+2+a;
    }
    ...
    int arr[func(2)]={1,2,3,4,5};	//ok !
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    扩展:static_assert表示静态断言,用于确定在编译时就确定的变量的值是否正确。

    如果正确,返回true ,什么都不做;错误,则返回false,显示静态断言失败。

    constexpr int a=10;
    static_assert(a==10,"error");	// 正确,什么都不做
    static_assert(func(2)==6,"error");	//错误,显示第二个字符串的内容,实际结果应该为5
    
    • 1
    • 2
    • 3

    conexpr的递归:

    constexpr int m_pow(int base, int exp)noexcept
    {
    	return (exp == 0) ? 1 : base * m_pow(base, exp - 1);
    }
    ...
    constexpr int res = m_pow(2, 5);//编译时计算
    static_assert(res == 32, "false");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:你有没有注意到,函数就一条语句? 只要你在函数中使用constexpr,则你必须保证函数就一行语句: return语句。 否则constexpr的作用就相当于没有,它就是一个普通的函数了,不是编译时常量了。

    • constexpr的声明与实现一定要在使用者的前面!

    • 使用constexpr标记的函数你怎么知道就一定执行了constexpr的功能呢? 即编译时就完成了。

      • 答案: 查看反汇编,这是调用constexpr求幂的函数,可以发现它直接把一个值赋值给了变量,完成了赋值,我们都知道普通的函数调用过程一定会经历 call 与 ret的过程,因此可以确定,他的确是在编译时就完成了!!

    在这里插入图片描述


    类中constexpr

    在类中也可以使用constexpr,可以放在除析构函数以外,任意的成员函数中,静态成员函数,构造函数都可以。

    构造函数使用constexpr: constexpr 修饰类的构造函数时:要求该构造函数的函数体必须为空,且采用初始化列表的方式为各个成员赋值时,必须使用常量表达式

    class Foo
    {
    public:
    	//注意,constexpr 修饰类的构造函数时:
    	//要求该构造函数的函数体必须为空,且采用初始化列表的方式为各个成员赋值时,必须使用常量表达式。
    	constexpr Foo(int a, const char* s)noexcept
    		:a(a), name(s) {}
    }
    ...
    constexpr Foo a{ 10, "ylh"};	//编译时初始化
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    完成一个类的浅拷贝的constexpr函数:

    template <typename T>
    constexpr T m_copy(const T& t)noexcept
    {
    	return t;
    }
    ...
    //如果缺少 constexpr:call  m_copy (07FF7B96F13DEh)  说明这就是一个普通的函数
    //如果带上 constexpr,则会发现不会调用call,即成功实现了常量表达式函数
    constexpr Foo b =  m_copy(a);	// OK  a在上面已经通过constexpr调用了constexpr的构造函数,因此b也通过constexpr实现了编译时拷贝。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    接收多个参数的constexpr函数:

    constexpr Foo ExChange(const Foo& a, const Foo& b)
    {
    	return { a.GetA() / 2,b.GetName() };
    }
    ...
    // 不会调用  call ExChange (07FF6F75013F7h)  
    constexpr Foo ExRes = ExChange(a, b);	//ok
    //使用static_assert判断正确性:
    static_assert(ExRes.GetA() == 5, "测试");	//是对的,因为ExRes.GetA()在函数中是来自与a的GetA函数除以2得到的,所以是10/2得5,因此正确
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    python 数据保存为npy和npz格式并读取
    一张图带你了解.NET终结(Finalize)流程
    使用.NET7和C#11打造最快的序列化程序-以MemoryPack为例
    2023最新SSM计算机毕业设计选题大全(附源码+LW)之java教务管理系统75850
    Numpy入门[11]——生成数组的函数
    【CAN】CAN基础概念5
    PyCharm连接远程Docker环境
    Android Studio for Platform (ASfP) 使用教程
    STM32H7 Azure RTOS
    Using LDAP to authenticate users
  • 原文地址:https://blog.csdn.net/jj6666djdbbd/article/details/127837154