一、constexpr意义

  将变量声明为constexpr类型以便由编译器来验证变量是否是一个常量表达式(不会改变,在编译过程中就能得到计算结果的表达式)。是一种比const更强的约束,这样可以得到更好的效率和安全性。

二、constexpr用法

  1.修饰函数

/*1.如果size在编译时能确定,那么返回值就可以是constexpr,编译通过*/
constexpr int getSizeA(int size)
{
return *size;
}
/*2.编译通过,有告警:在constexpr中定义变量*/
constexpr int getSizeB(int size)
{
int index = ;
return ;
}
/*3.编译通过,有告警:在constexpr中定义变量(这个有点迷糊)*/
constexpr int getSizeC(int size)
{
constexpr int index = ;
return ;
}
/*4.编译通过,有告警:使用了if语句(使用switch也会告警)*/
constexpr int getSizeD(int size)
{
if()
{}
return ;
}
/*5.定义变量并且没有初始化,编译不过*/
constexpr int getSizeE(int size)
{
int index;
return ;
}
/*6.rand()为运行期函数,不能在编译期确定,编译不过*/
constexpr int getSizeF(int size)
{
return *rand();
}
/*7.使用了for,编译不过*/
constexpr int getSizeG(int size)
{
for(;;)
{}
return *rand();
}

  总结:constexpr修饰的函数,不能依赖任何运行期的信息,不要定义任何变量常量,并且必须尽量简单,要不就会编译不过或告警(坑)。

  2.修饰类型

    int tempA;
cin>>tempA; const int ctempA = ;
const int ctempB = tempA;
/*1.可以再编译器确定,编译通过*/
constexpr int conexprA = ;
constexpr int conexprB = conexprA + ;
constexpr int conexprC = getSizeA(conexprA);
constexpr int conexprD = ctempA;
/*2.不能在编译期决定,编译不过*/
constexpr int conexprE = tempA;
constexpr int conexprF = ctempB;

  总结:constexpr修饰的常量必须在编译期确定值,上面的例子也体现出了和const之间的差别。const既可以在编译期确定如ctempA,也可以在运行期确定如ctempB,使用范围更广。还有一点constexpr只能修饰字面值类型如算数类型、引用类型、指针以及后面介绍的字面值常量类。

  3.修饰指针

int g_tempA = ;
const int g_conTempA = ;
constexpr int g_conexprTempA = ; int main(void)
{
int tempA = ;
const int conTempA = ;
constexpr int conexprTempA = ; /*1.正常运行,编译通过*/
const int *conptrA = &tempA;
const int *conptrB = &conTempA;
const int *conptrC = &conexprTempA;
/*2.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/
constexpr int *conexprPtrA = &tempA;
constexpr int *conexprPtrB = &conTempA
constexpr int *conexprPtrC = &conexprTempA;
/*3.第一个通过,后面两个不过,因为constexpr int *所限定的是指针是常量,故不能将常量的地址赋给顶层const*/
constexpr int *conexprPtrD = &g_tempA;
constexpr int *conexprPtrE = &g_conTempA
constexpr int *conexprPtrF = &g_conexprTempA;
/*4.局部变量的地址要运行时才能确认,故不能在编译期决定,编译不过*/
constexpr const int *conexprConPtrA = &tempA;
constexpr const int *conexprConPtrB = &conTempA;
constexpr const int *conexprConPtrC = &conexprTempA;
/*5.正常运行,编译通过*/
constexpr const int *conexprConPtrD = &g_tempA;
constexpr const int *conexprConPtrE = &g_conTempA;
constexpr const int *conexprConPtrF = &g_conexprTempA; return ;
}

  总结:constexpr指针不能用局部变量赋值,const指针可以;constexpr指针里是顶层const,即指针是常量,而不是所指向的类型是常量,如果要指向的类型也为常量,要用constexpr const来修饰。

4.修饰引用

int g_tempA = ;
const int g_conTempA = ;
constexpr int g_conexprTempA = ; int main(void)
{
int tempA = ;
const int conTempA = ;
constexpr int conexprTempA = ;
/*1.正常运行,编译通过*/
const int &conptrA = tempA;
const int &conptrB = conTempA;
const int &conptrC = conexprTempA;
/*2.有两个问题:一是引用到局部变量,不能再编译器确定;二是conexprPtrB和conexprPtrC应该为constexpr const类型,编译不过*/
constexpr int &conexprPtrA = tempA;
constexpr int &conexprPtrB = conTempA
constexpr int &conexprPtrC = conexprTempA;
/*3.第一个编译通过,后两个不通过,原因是因为conexprPtrE和conexprPtrF应该为constexpr const类型*/
constexpr int &conexprPtrD = g_tempA;
constexpr int &conexprPtrE = g_conTempA;
constexpr int &conexprPtrF = g_conexprTempA;
/*4.正常运行,编译通过*/
constexpr const int &conexprConPtrD = g_tempA;
constexpr const int &conexprConPtrE = g_conTempA;
constexpr const int &conexprConPtrF = g_conexprTempA; return ;
}

  总结:简单的说constexpr所引用的对象必须在编译期就决定地址。还有一个奇葩的地方就是可以通过上例conexprPtrD来修改g_tempA的值,也就是说constexpr修饰的引用不是常量,如果要确保其实常量引用需要constexpr const来修饰。

5.修饰类(未完待续)

C++11新标准:constexpr关键字的更多相关文章

  1. C++11新标准:nullptr关键字

    一.nullptr的意义 1.NULL在C中的定义 #define NULL (void*)0 2.NULL在C++中的定义 #ifndef NULL #ifdef __cplusplus #defi ...

  2. C++11新标准:decltype关键字

    一.decltype意义 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了).为了满足这一需求,C++11新标准引入了decltype类型 ...

  3. C++11新标准:auto关键字

    一.auto意义 编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型,然后要做到这一点并非那么容易.为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能 ...

  4. C++11新标准学习

    <深入理解C++11:C++11新特性解析与应用> <华章科技:深入理解C++11:C++11新特性解析与应用>一共8章:第1章从设计思维和应用范畴两个维度对C++11新标准中 ...

  5. c++11新标准for循环和lambda表达式

    :first-child { margin-top: 0px; } .markdown-preview:not([data-use-github-style]) h1, .markdown-previ ...

  6. 关注C++细节——C++11新标准之decltype的使用注意

    c++11新特性--decltype decltype是C++11加入的一个新的keyword,目的是选择并返回操作数的数据类型,重要的是,在此过程中编译器分析表达式并得到它的类型,却不实际计算表达式 ...

  7. 基于c++11新标准开发一个支持多线程高并发的网络库

    背景 新的c++11标准出后,c++语法得到了非常多的扩展,比起以往不论什么时候都要灵活和高效,提高了程序编码的效率,为软件开发者节省了不少的时间. 之前我也写过基于ACE的网络server框架,但A ...

  8. C++11新标准

    1. 新类型 long long和unsigned long long: char16_t 和 char32_t: 新增原始字符串: 2. 统一的初始化 C++11扩大了用大括号括起的列表(初始化列表 ...

  9. C++ 11新标准实现POJ No.1002-487-3279

    487-3279(重复的电话号码查询)(标签:优先队列,哈希表) 题目描述 企业喜欢用容易被记住的电话号码.让电话号码容易被记住的一个办法是将它写成一个容易记住的单词或者短语.例如,你需要给滑铁卢大学 ...

随机推荐

  1. Python函数-all()

    all(iterable) 作用: 如果iterable的所有元素不为0.''.False或者iterable为空,all(iterable)返回True,否则返回False:函数等价于: def a ...

  2. ubuntu更改用户登录密码

    sudo passwd user(root或对应的用户名)

  3. Linux动态gif图的录制

    Linux动态gif图的录制 Linux动态gif图的录制 byzanz的安装与使用 recordmydesktop再convert成gif 参考资料 前几天写了两篇博客vim的配置和Vim的自动代码 ...

  4. [转]理解$watch ,$apply 和 $digest --- 理解数据绑定过程

    原文地址:http://angular-tips.com/blog/2013/08/watch-how-the-apply-runs-a-digest/ 注 这篇博文主要是写给新手的,是给那些刚刚开始 ...

  5. 五、Jmeter--关联(正则表达式)

    一.什么时候需要关联? 1. 服务器返回的动态变化而且对业务有影响的需要关联. 2. 回放脚本看是否正确,检查下脚本,是否有动态数据影响 3. 一大串字符串,每次请求参数是否有变化 4. 可以找开发问 ...

  6. boost1_55_0编译和安装

    1.在www.boost.org下载文件并解压 2.进行解压目录 2.1 编译前的配置工作 执行bootstrap.bat  windows 使用vs2010: 修改\boost_1_55_0\too ...

  7. Linux测试程序 - 多线程

    #include <sched.h> #include <pthread.h> main(){ pthread_t id0, id1, id2; ret=pthread_cre ...

  8. Jenkins关闭、重启,Jenkins服务的启动、停止方法。

     一.Jenkins关闭.重启 1.关闭Jenkins 只需要在访问jenkins服务器的网址url地址后加上exit,关闭Jenkins服务. 例如:http://localhost:8081/ex ...

  9. PostgreSQL 9.5 客户端认证

    PostgreSQL 9.5 客户端认证 当一个客户端应用连接一个数据库服务器时,它将指定以哪个PostgreSQL 数据库用户名连接,就像我们以一个特定用户登录一台 Unix 计算机一样.在 SQL ...

  10. phonegap制作windows phone包

    下载SDK win7及以下版本下载SDK http://www.microsoft.com/zh-cn/download/confirmation.aspx?id=27570 WIN8下载SDK ht ...