常量表达式函数

要求:

  1. 函数体内只有单一的return返回语句

    例如:
constexpr int data()
{
const int i=1; //含有除了return以外的语句
return i;
}

在c++11中是无法通过编译的。

但使用不会产生实际代码的语句是可以的,例如static_assert()

2. 函数必须返回值

例如constexpr void f(){}无法通过编译的,因为无法获得常量的常量表达式是不被认可的。

3. 在使用前必须已有定义

constexpr int f();
constexpr int c=f(); //无法通过编译
constexpr int f(){return 1;}
  1. return返回语句表达式中不能使用非常量表达式的函数、全局数据,且必须是一个常量表达式。
const int e(){return 1;}
constexpr int g(){return e();} //编译错误,使用了非常量表达式的函数

常量表达式值

const int i=1;
constexpr int j=1;

两者在大多数情况下没有区别,但如果i在全局名称空间中,编译器一定会为i产生数据。而对于j,如果不是有代码显式地使用了它的地址,编译器可以选择不为它生成数据,而仅将其当作编译时期的值。

在C++11中constexpr是不能用于自定义类型的,例如:

constexpr struct MyType{int i;}
constexpr MyType mt={0};

将无法通过编译。正确的做法是,定义自定义常量构造函数:

struct MyType
{
constexpr MyType(int x):i(x){}
int i;
};
constexpr MyType mt = { 0 };

常量表达式的构造函数也有使用上的约束:

  1. 函数体必须为空
  2. 初始化列表只能由常量表达式来赋值。

此外,在C++11中,不允许常量表达式作用于virtual的成员函数。vitual是运行时的行为,与编译期计算的constexpr的意义是冲突的。

常量表达式的构造函数也可以用于非常量表达式中的类型构造,且无法重写。

其他应用

模板函数

常量表达式是可以用于模板函数的,不过由于模板中类型的不确定性,所以模板函数是否会被实例化为一个能够满足编译时常量性的版本通常也是未知的。C++11标准规定:当声明为常量表达式的模板函数后,而某个该模板函数的实例化结果不满足常量表达式的需求的话,constexpr会被自动忽略。该实例化后的函数将成为一个普通函数。

例如:

struct NotLiteral
{
NotLiteral(){i=5;}
int i;
};
NotListeral nl; template<class T>
constexpr T ConstExp(T t)
{
return t;
}
void g()
{
NotLiteral nl;
NotLiteral nl1=ConstExp(nl);
constexpr NotLiteral nl2=ConstExp(nl); //无法编译
constexpr int a=ConstExp(1); //OK
}

代码中NotLiteral不是一个定义了常量表达式构造函数的类型,因此不能够声明为常量表达式值。而模板函数ConstExp一旦以NotLiteral为参数的话,那么其constexpr关键字将被忽略。

递归

常量表达式支持至少512层的递归,可以在编译期充当“计算器”。

constexpr int Fibonacci(int n)
{
return (n == 1) ? 1 : ((n == 2) ? 2 : Fibonacci(n - 1) + Fibonacci(n - 2));
} Fibonacci(12);

然而并不是使用了constexpr,编译器就一定会在编译期间对常量表达式函数进行值计算。标准只是定义了可以用于编译时进行值计算的常量表达式的定义,却没有强制要求编译器一定在编译时进行值计算。(经反汇编,上述代码在vs2017debug下未在编译期计算出结果)所以编译器通过一些手段绕过代码的语法,仍然做运行时的调用,这样也是符合C++11的。

内容摘自《深入理解C++11》

C++11 constexpr常量表达式的更多相关文章

  1. C++11特性——变量部分(using类型别名、constexpr常量表达式、auto类型推断、nullptr空指针等)

    #include <iostream> using namespace std; int main() { using cullptr = const unsigned long long ...

  2. C++11常量表达式

    [C++11之常量表达式] 关键字:constexpr: 中文学名:常量表达式. constexpr用于把运行期计算放置在编译期. 使用constexpr有3个限制: 1.函数中只能有一个return ...

  3. 常量表达式和constexpr(c++11)

    常量表达式 常量表达式是指值不会改变且在编译阶段就能得到计算结果的表达式(两点要求) ; //是常量表达式 ; //是常量表达式 "; const int siz=s.size(); //不 ...

  4. constexpr与常量表达式(c++11标准)

    关键字 constexpr 是C++11中引入的关键字,是指值不会改变并且在编译过程中就得到计算结果的表达式.(运行中得到结果的不能成为常量表达式,比如变量). 声明为constexpr的变量一定是一 ...

  5. C++常量表达式、const、constexpr(C++11新增)的区别

    常量表达式是指值不会改变且在编译过程中就能够得到计算结果的表达式,能在编译时求值的表达式. 程序先编译再运行:  在编译阶段, 编译器将在编译过程中把用到该常量的地方都全都替换为 常量的值. 但是常量 ...

  6. constexpr和常量表达式

    常量表达式:值不会改变并且在编译过程就能得到计算结果的表达式. 字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式. 一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同 ...

  7. constexpr和常量表达式的注意事项

    1.常量表达式,是指其值不可改变,且在编译阶段就已经得出计算结果的表达式,例如字面值就是常量表达式. 2.判断是否是常量表达式,要关注数据类型是否是const类型,初始值是否是在编译阶段就得到的. 3 ...

  8. 第8课 常量表达式(constexpr)

    一. const 和constexpr的区别 (一)修饰变量时,const为“运行期常量”,即运行期数据是只读的.而constexpr为“编译期”常量,这是const无法保证的.两者都是对象和函数接口 ...

  9. c++11 常量表达式

    c++11 常量表达式 #define _CRT_SECURE_NO_WARNINGS #include <iostream> #include <string> #inclu ...

随机推荐

  1. js空数组

    首先我们定义一个空的数组: var a = [ ]; 数组a里面是空的没有值,接下来我们打印: console.log(!!a); 因为数组是空的,此处应该为false. 恰好相反,!!a为true. ...

  2. alpha冲刺(3/10)

    前言 队名:旅法师 作业链接 队长博客 燃尽图 会议 会议照片 会议内容 陈晓彬(组长) 今日进展: 召开会议 安排任务 博客撰写 制定计划 问题困扰: 前后端的交互沟通有点缺失,以至后端进度很慢,需 ...

  3. 2018.4.28 kvm虚拟机管理

    创建虚拟机: virt-install --name wj-v1.4.1.0411 --vcpus=2 --memory=2048 --disk path=/home/wj/os/osgwV1.4.1 ...

  4. 第十七章 java8特性

    17.java8中Lambda表达式与Stream API的使用 17.1 Lambda 表达式(Lambda Expressions) 1课时 17.2 函数式(Functional)接口 1课时 ...

  5. WebApi 序列化 循环引用问题

    public static void Register(HttpConfiguration config) { // Web API 配置和服务 config.Formatters.Remove(co ...

  6. CentOS7版本区别和下载

    CentOS 7提供了三种ISO镜像文件的下载: DVD ISO 标准安装版,一般下载这个就可以了(推荐) Everything ISO 对完整版安装盘的软件进行补充,集成所有软件.(包含centos ...

  7. msvcp140.dll丢失解决方案

    [首先给出99%情况下都能解决这个问题的最简单办法]:   下载并安装微软VC++2015版运行库 (英文全称:Microsoft Visual C++ 2015 Redistributable Pa ...

  8. jsp 进度条

    <html>  <head>  <title>进度条</title>  <style type="text/css">  ...

  9. 报错:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1

    错误现象: Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-com ...

  10. Python微信

    """ Description: 需要提供以下三个信息,在申请到的微信企业号当中可以找到 agentid corpid corpsecret Author:Nod Dat ...