• C++ constexpr类型说明符



    本系列文章由 @yhl_leo 出品,转载请注明出处。
    文章链接: http://blog.csdn.net/yhl_leo/article/details/50864210


    关键字 constexpr 于 C++11 中引入并于 C++14 中得到改善。它表示常数表达式。与 const 相同,它可应用于变量,因此如果任何代码试图修改该值,均将引发编译器错误。与 const 不同,constexpr 也可应用于函数和类构造函数。 constexpr 指示值或返回值是常数,并且如果可能,将在编译时计算值或返回值。

    1 constexpr 变量

    constconstexpr 变量之间的主要区别在于:const 变量的初始化可以延迟到运行时,而 constexpr 变量必须在编译时进行初始化。所有 constexpr 变量均为常量,因此必须使用常量表达式初始化。

    constexpr float x = 42.0;
    constexpr float y{108};
    constexpr float z = exp(5, 3);
    constexpr int i; // Error! Not initialized
    int j = 0;
    constexpr int k = j + 1; //Error! j not a constant expression

    一般来说,如果你认定变量是一个常量表达式,那就把它声明成为constexpr类型。

    2 constexpr 函数

    constexpr 函数是在使用需要它的代码时,可以在编译时计算其返回值的函数。当其参数为 constexpr 值并且在编译时使用代码需要返回值时(例如,初始化一个 constexpr 变量或提供一个非类型模板参数),它会生成编译时常量。使用非constexpr 参数调用时,或编译时不需要其值时,它将与正则函数一样,在运行时生成一个值。

    #include <iostream>
    
    using namespace std;
    
    // Pass by value 
    constexpr float exp(float x, int n)
    {
        return n == 0 ? 1 :
            n % 2 == 0 ? exp(x * x, n / 2) :
            exp(x * x, (n - 1) / 2) * x;
    };
    
    // Pass by reference
    constexpr float exp2(const float& x, const int& n)
    {
        return n == 0 ? 1 :
            n % 2 == 0 ? exp2(x * x, n / 2) :
            exp2(x * x, (n - 1) / 2) * x;
    };
    
    // Compile time computation of array length
    template<typename T, int N>
    constexpr int length(const T(&ary)[N])
    {
        return N;
    }
    
    // Recursive constexpr function
    constexpr int fac(int n)
    {
        return n == 1 ? 1 : n*fac(n - 1);
    }
    
    // User-defined type
    class Foo
    {
    public:
        constexpr explicit Foo(int i) : _i(i) {}
        constexpr int GetValue()
        {
            return _i;
        }
    private:
        int _i;
    };
    
    int main()
    {
        // foo is const:
        constexpr Foo foo(5);
        // foo = Foo(6); // Error!
    
        //Compile time:
        constexpr float x = exp(5, 3);
        // const float a = 2.0;
        // const int  b  = 2;
        // constexpr float xx = exp2(a, b); // Error!
        constexpr float xx = exp2(2.0, 2);
        constexpr float y{ exp(2, 5) };
        constexpr int val = foo.GetValue();
        constexpr int f5 = fac(5);
        const int nums[]{ 1, 2, 3, 4 };
        const int nums2[length(nums) * 2]{ 1, 2, 3, 4, 5, 6, 7, 8 };
    
        cout << "The value of foo is " << foo.GetValue() << endl;
    
    }

    3 constexpr和指针

    还记得const与指针的规则吗?如果关键字const出现在星号左边,表示被指物是常量;如果出现在星号右边,表示指针本身是常量;如果出现在星号两边,表示被指物和指针两者都是常量。

    const不同,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指对象无关

    const int *p     = 0; // non-const pointer, const data
    constexpr int *q = 0; // const pointer, non-const data

    与其它常量指针类似,const指针既可以指向常量也可以指向一个非常量:

    int j = 0;
    constexpr int i = 2;
    constexpr const int *p = &i; // const pointer, const data
    constexpr int *p1 = &j; // const pointer, non-const data
  • 相关阅读:
    vue 无缝无限滚动横条实现
    小程序 recycle-view 个人demo
    js 笔记
    java整理的一些面试资料
    使用js获取浏览器地址栏里的参数
    java面试题
    sql中索引不会被用到的几种情况
    常用linux命令
    shiro登录成功之后跳转原路径
    springboot 整合 mongodb实现 批量更新数据
  • 原文地址:https://www.cnblogs.com/hehehaha/p/6332150.html
Copyright © 2020-2023  润新知