zoukankan      html  css  js  c++  java
  • 常量表达式

    constexpr初探

    为了使函数获取编译时计算的能力,你必须指定constexpr关键字到这个函数。

    constexpr int multiply (int x, int y)
    {
        return x * y;
    }
    
    // 将在编译时计算
    const int val = multiply( 10, 10 );  

    除了编译时计算的性能优化,constexpr的另外一个优势是,它允许函数被应用在以前调用宏的所有场合。例如,你想要一个计算数组size的函数,size是10的倍数。如果不用constexpr,你需要创建一个宏或者使用模板,因为你不能用函数的返回值去声明数组的大小。但是用constexpr,你就可以调用一个constexpr函数去声明一个数组。

    constexpr int getDefaultArraySize (int multiplier)
    {
        return 10 * multiplier;
    }
    
    int my_array[ getDefaultArraySize( 3 ) ];  

    constexpr函数的限制

    一个constexpr有一些必须遵循的严格要求:

    • 函数中只能有一个return语句(有极少特例)
    • 只能调用其它constexpr函数
    • 只能使用全局constexpr变量

    注意递归并不受限制。但只允许一个返回语句,那如何实现递归呢?可以使用三元运算符(?:)。例如,计算n的阶乘:

    constexpr int factorial (int n)
    {
        return n > 0 ? n * factorial( n - 1 ) : 1;
    }

    现在你可以使用factorial(2),编译器将在编译时计算这个值,这种方式运行更巧妙的计算,与内联截然不同。你无法内联一个递归函数。

    constexpr函数还有那些特点?

    一个constexpr函数,只允许包含一行可执行代码。但允许包含typedefs、 using declaration && directives、静态断言等。

    constexpr和运行时

    一个声明为constexpr的函数同样可以在运行时被调用,当这个函数的参数是非常量的:

    int n;
    cin >> n;
    factorial( n );

    这意味着你不需要分别写运行时和编译时的函数。

    编译时使用对象

    假如你有一个Circle类:

    class Circle
    {
        public:
        Circle (int x, int y, int radius) : _x( x ), _y( y ), _radius( radius ) {}
        double getArea () const
        {
            return _radius * _radius * 3.1415926;
        }
        private:
            int _x;
            int _y;
            int _radius;
    };

    你希望在编译期构造一个Circle接着算出他的面积。

    constexpr Circle c( 0, 0, 10 );
    constexpr double area = c.getArea();

    事实证明你可以给Circle类做一些小的修改以完成这件事。首先,我们需要将构造函数声明为constexpr,接着我们需要将getArea函数声明为constexpr。将构造函数声明为constexpr则运行构造函数在编译期运行,只要这个构造函数的参数为常量,且构造函数仅仅包含成员变量的constexpr构造(所以默认构造可以看成constexpr,只要成员变量都有constexpr构造)。

    class Circle
    {
        public:
        constexpr Circle (int x, int y, int radius) : _x( x ), _y( y ), _radius( radius ) {}
        constexpr double getArea ()
        {
            return _radius * _radius * 3.1415926;
        }
        private:
            int _x;
            int _y;
            int _radius;
    };

    constexpr vs const

    假如你将一个成员函数标记为constexpr,则顺带也将它标记为了const。如果你将一个变量标记为constexpr,则同样它是const的。但相反并不成立,一个const的变量或函数,并不是constexpr的。

    constexpr和浮点数

    到这里我们讲到的constexpr功能都可以通过模板元编程实现。但constexpr支持的一项能力是可以计算浮点型的数据。因为double和float不是有效的模板参数,你不可以轻易的通过模板编译期计算浮点数的值。而constexpr允许编译期计算浮点型数据。

    原文博客:http://towriting.com/blog/2013/09/17/constexpr/

  • 相关阅读:
    [PHP] ::class的具体作用
    [linux] 查看所有的系统用户
    [PHP] composer install和composer update的区别
    [PHP] 解决composer install报错: it could not be found in any version, there may be a typo in the package name
    [git] git中origin的含义
    [git] 打标签命令
    [git] git clone指定分支代码
    [git]git中分支的概念
    [PHP] 对象和引用
    [正则]正则表达式里面的?: ?! ?= ?<=
  • 原文地址:https://www.cnblogs.com/ThatsMyTiger/p/7089956.html
Copyright © 2011-2022 走看看