C++11 FAQ中文版:常量表达式(constexpr)

长平狐 发布于 2013/01/11 10:33
阅读 123
收藏 0

常量表达式(constexpr) — 一般化的受保证的常量表达式

常量表达式机制是为了:

  • 提供了更多的通用的值不发生变化的表达式
  • 允许用户自定义的类型成为常量表达式
  • 提供了一种保证在编译期完成初始化的方法(可以在编译时期执行某些函数调用)

考虑下面这段代码:

    enum Flags { good=0, fail=1, bad=2, eof=4 };

    constexpr int operator|(Flags f1, Flags f2)
    { return Flags(int(f1)|int(f2)); }

    void f(Flags x)
    {
        switch (x) {
        case bad:         /* … */ break;
        case eof:         /* … */ break;
        case bad|eof:     /* … */ break;
        default:          /* … */ break;
        }
    }

在这里,常量表达式关键字constexpr表示这个重载的操作符“|”就应该像一个简单的表单一样,如果它的参数本身就是常量 ,那么这个操作符应该在编译时期就应该计算出它的结果来。(译注: 我们都知道,switch的分支条件要求常量,而使用constexpr关键字重载操作符“|”之后,虽然“bad|eof”是一个表达式,但是因为这两个参数都是常量,在编译时期,就可以计算出它的结果,因而也可以作为常量对待。)
除了可以在编译时期被动地计算表达式的值之外,我们希望能够主动地要求表达式在编译时期计算其结果值,从而用作其它用途,比如对某个变量进行赋值。当我们在变量声明前加上constexpr关键字之后,可以实现这一功能,当然,它也同时会让这个变量成为常量。

    constexpr int x1 = bad|eof;    // ok

    void f(Flags f3)
    {
        // 错误:因为f3不是常量,所以无法在编译时期计算这个表达式的结果值
        constexpr int x2 = bad|f3;
        int x3 = bad|f3;     // ok,可以在运行时计算
    }

通常,我们希望编译时期计算可以保护全局或者名字空间内的对象,对名字空间内的对象,我们希望它保存在只读空间内。
对于那些构造函数比较简单,可以成为常量表达式(也就是可以使用constexpr进行修饰)的对象可以做到这一点(?)

    struct Point {
        int x,y;
        constexpr Point(int xx, int yy) : x(xx), y(yy){}
    };

    constexpr Point origo(0,0);
    constexpr int z = origo.x;

    constexpr Point a[] = {Point(0,0), Point(1,1), Point(2,2) };
    constexpr x = a[1].x;    // x 变成 1 (译注:这里的代码似乎有问题?)

(zwvista的一段评论,有助于我们理解constexpr的意义,感谢zwvista。constexpr 将编译期常量概念延伸至括用户自定义常量以及常量函数,其值的不可修改性由编译器保证,因而constexpr 表达式是一般化的,受保证的常量表达式。)

参考:

(翻译:陈良乔,感谢:zwvista)

0
Leave a comment

原文链接:http://blog.csdn.net/fjb2080/article/details/7527202
加载中
返回顶部
顶部