C++新标准:constexpr关键字

一、constexpr意义

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

二、constexpr用法

  1.修饰函数

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

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

  2.修饰类型

    int tempA;
    cin>>tempA;

    const int ctempA = 4;
    const int ctempB = tempA;
    /*1.可以再编译器确定,编译通过*/
    constexpr int conexprA = 4;
    constexpr int conexprB = conexprA + 1;
    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 = 4;
const int g_conTempA = 4;
constexpr int g_conexprTempA = 4;

int main(void)
{
    int tempA = 4;
    const int conTempA = 4;
    constexpr int conexprTempA = 4;

    /*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 0;
}

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

4.修饰引用

int g_tempA = 4;
const int g_conTempA = 4;
constexpr int g_conexprTempA = 4;

int main(void)
{
    int tempA = 4;
    const int conTempA = 4;
    constexpr int conexprTempA = 4;
    /*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 0;
}

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

5.修饰类(未完待续)

时间: 2024-10-12 21:16:22

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

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

一.nullptr的意义 1.NULL在C中的定义 #define NULL (void*)0 2.NULL在C++中的定义 #ifndef NULL #ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif #endif 3.为什么C++和C中NULL定义不一样呢? void foo(int a) { cout<<"This is int"<<endl; } void foo

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

一.decltype意义 有时我们希望从表达式的类型推断出要定义的变量类型,但是不想用该表达式的值初始化变量(如果要初始化就用auto了).为了满足这一需求,C++11新标准引入了decltype类型说明符,它的作用是选择并返回操作数的数据类型,在此过程中,编译器分析表达式并得到它的类型,却不实际计算表达式的值. 二.decltype用法 1.基本用法 int getSize(); int main(void) { int tempA = 2; /*1.dclTempA为int*/ declty

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

一.auto意义 编程时常常需要把表达式的值赋给变量,这就要求在声明变量的时候清楚地知道表达式的类型,然后要做到这一点并非那么容易.为了解决这个问题,C++11新标准引入了auto类型说明符,用它就能让编译器替我们去分析表达式所属的类型. 二.auto用法 1.基本用法 int tempA = 1; int tempB = 2; /*1.正常推断auto为int,编译通过*/ auto autoTempA = tempA + tempB; /*2.正常推断auto为int,编译通过*/ auto

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

c++11新特性--decltype decltype是C++11添加的一个新的关键字,目的是选择并返回操作数的数据类型,重要的是,在此过程中编译器分析表达式并得到它的类型,却不实际计算表达式的值. 对于内置类型的对象,使用decltype很直观,但当参数为复合类型的时候就应该注意一些使用细节问题. 1.当decltype作用于数组的时候就应该小心了,本文作者(CSDN   iaccepted). intiarr[10] = {0}; decltype(iarr)ib; 这个时候ib的定义等价于

多态实现的原理------新标准c++程序设计

"多态"的关键在于通过基类指针或引用调用一个虚函数时,编译时不确定到底调用的是基类还是派生类的函数,运行时才确定.例子: #include<iostream> using namespace std; class A{ public: int i; virtual void func(){}; virtual void func2(){}; //如果为只有一个去掉 virtual 关键字即virtual void func2(){};变为 void func2(){}; 输

[原]C++新标准之std::chrono::duration

原 总结 C++11 chrono duration ratio 概览 std::chrono::duration 描述 类定义 duration_cast()分析 预定义的duration 示例代码 参考资料 概览 c++新标准提供了新的线程库,最近在写测试代码的时候需要让当前线程休眠,之前直接调用windows提供的Sleep()就好了,新标准中可以使用std::this_thread::sleep_for()或者std::this_thread::sleep_until() 来实现休眠.其

《Javascript权威指南》学习笔记之十九--HTML5 DOM新标准---处理文档元信息和管理交互能力

一.了解DOM 1.DOM是Document Object Model的缩写,即文档对象类型,是文档在内存中的表示形式,是一个应用程序接口,定义了文档的逻辑结构以及一套访问和处理文档的方法. 2.HTML DOM与Core DOM的区别:前者提供了大量的方法和属性,与现有的程序模型一致,更便于脚本的编写者控制. 二.document对象 使用window.document属性返回一个document对象,代表当前window内加载的文档.window可以省略.winName.document返回

C++旧源码向新标准移植陷井(一)_局部栈变量的生命周期

之前在VC++6.0上面写了下面这样的代码: int _tmain(int argc, TCHAR* argv[], TCHAR* envp[]) { int nRetCode = 0; //不重要的部分略过if (argc>1) {if (strcmp(argv[1],"createpcsstep") == 0) { CDlgCreateStepPcs dlg; dlg.DoModal(); break; } else if (strcmp(argv[1],"clea

P2P联合银行 如何打造行业安全新标准?

在中国互联网领域里,互联网金融的发展时间几乎堪称最短,但互联网金融对国计民生和互联网经济所起到的促进与推荐作用,却远远超过其他任何互联网业务分支.在今天,基于移动终端和移动互联网的并行发展,以及互联网金融在普通大众生活.工作等领域的普遍应用,目前的互联网金融正在进入全新的生活服务领域,并以其巨大的渗透力改变着大众生活. 除了习以为常的金融信贷业务之外,互联网金融在今天的局面已经延伸和扩展到更多领域,其中较为明显的有征信体系.互联网信用系统建设等系统工作,这些业务虽然基于互联网方式而展开,但其对于

软件产品质量 “新”标准

? Erik van Veenendaal( www.erikvanveenendaal.nl )是一名国际知名的尖端顾问和培训师,和一名在软件测试和质量管理领域广受认可的专家.他是Improve Quality Services BV(www.improveqs.nl)的创始人.他保持着欧洲之星的记录,三次获得最佳导师将!2007年,因其对测试专业做出多年贡献,他获得了欧洲测试优秀奖.他作为测试经理和顾问在各个领域工作了20多年.他撰写了多篇论文和多部著作,包括"实用基于风险的测试: Pris