一、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. Redis底层探秘(三):字典

    字典,又称为符号表(symbol table).关联数组(associative array)或映射(map),是一种用于保存键值对的抽象数据结构. 字典经常作为一种数据结构内置在很多高级编程语言里面 ...

  2. 统计数字noip2007

    7909:统计数字 总时间限制:  1000ms 内存限制:  65536kB 描述 某次科研调查时得到了n个自然数,每个数均不超过1500000000(1.5*109).已知不相同的数不超过1000 ...

  3. Python函数-enumerate()

    enumerate(sequence, [start=0]) 作用: 将可循环序列sequence以start开始分别列出序列数据和数据下标,即对一个可遍历的数据对象(如列表.元组或字符串),enum ...

  4. Linux sed 批量替换多个文件中的字符串【转载】

    原文网址:http://blog.sina.com.cn/s/blog_730edb930100qzz5.html     比如,要将目录/modules下面所有文件中的zhangsan都修改成lis ...

  5. bzoj 3771 Triple——FFT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3771 把方案作为系数.值作为指数,两项相乘就是系数相乘.指数相加,符合意义. 考虑去重.先自 ...

  6. flask之全局对象

    from flask import current_app, g g is a special object that is unique for each request. It is used t ...

  7. 机器学习:模型泛化(LASSO 回归)

    一.基础理解 LASSO 回归(Least Absolute Shrinkage and Selection Operator Regression)是模型正则化的一定方式: 功能:与岭回归一样,解决 ...

  8. pycharm中 unittests in xxxx 运行模式

    pycham中 当你运行时 ,使用的 是  Run "unittests in  xxxx" 模式时候,if __name__ == '__main__':  后面的代码是不执行的 ...

  9. Rozor视图(c#代码与html混合编程原则)

    (1)大括号的匹配原则(就近原则){} (2)html标签有截断c#代码的功能 @*服务器端的注释*@    <!--客户端注释-->

  10. JAVA基础知识总结12(多线程)

    进程:正在进行中的程序.其实进程就是一个应用程序运行时的内存分配空间. 线程:其实就是进程中一个程序执行控制单元,一条执行路径.进程负责的是应用程序的空间的标示.线程负责的是应用程序的执行顺序. 一个 ...