C++11关键字constexpr看这篇就够了

C++11关键字constexpr看这篇就够了一 在普通函数中的使用例如下面的代码 数组的大小必须是常量 在声明数组 array 时 用函数返回值 此时会报错 errorC2131 表达式的计算结果不是常数 note 对未定义的函数或为未声明为 constexpr 的函数的调用导致了故障用 constexpr 关键字可以解决这种问题 在 GetLen 函数前加 constexpr 声明 代码如下 当然 constexpr 修饰的函数也有一定的限制 函数体尽量只包含一个 return 语句 多个可能会编译出错

一、在普通函数中的使用

例如下面的代码,

C++11关键字constexpr看这篇就够了

数组的大小必须是常量,在声明数组array时,用函数返回值,此时会报错:

error C2131: 表达式的计算结果不是常数

note: 对未定义的函数或为未声明为“constexpr”的函数的调用导致了故障

用constexpr关键字可以解决这种问题,在GetLen函数前加constexpr声明,代码如下:

C++11关键字constexpr看这篇就够了

编译器会将constexpr函数视为内联函数!所以在编译时若能求出其值,则会把函数调用替换成结果值。

二、在类的构造函数中也可以使用constexpr关键字

        代码如下:

#include <iostream> using namespace std; class Test { public: constexpr Test(int num1, int num2) : m_num1(num1), m_num2(num2) { } public: int m_num1; int m_num2; }; int main(void) { constexpr Test t1(1, 2); enum e { x = t1.m_num1, y = t1.m_num2 }; return 0; }

  如果在构造函数中加点代码,就会编译报错,如下:

C++11关键字constexpr看这篇就够了

三、const和constexpr对指针的修饰有什么差别呢?

(1)const 和 constexpr 变量之间的主要区别在于:const 变量的初始化可以延迟到运行时,而 constexpr 变量必须在编译时进行初始化。所有 constexpr 变量均为常量,因此必须使用常量表达式初始化。

       与const不同,在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指对象无关。

       constexpr是一种很强的约束,更好的保证程序的正确定语义不被破坏;编译器可以对constexper代码进行非常大的优化,例如:将用到的constexpr表达式直接替换成结果, 相比宏来说没有额外的开销。

       代码:

#include <iostream> using namespace std; 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; }

四、对引用的修饰

  代码如下:

#include <iostream> using namespace std; 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来修饰。

       以上是C++ 11 constexpr的简单应用,要深入学好C++,需要长期的训练,刻意练习。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/233215.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • Java输入输出(标准)

    Java输入输出(标准)简述Java输入就需要自己构造类了。其中nextLine()这个方法,表示的是,一直读,读到有换行符之后就截至(不取换行符)代码importjava.util.*;publicclassTest{publicstaticvoidmain(String[]args){Scannerin=newScanner(System….

    2022年5月15日
    38
  • Linux 服务器环境搭建及配置[通俗易懂]

    Linux常用命令查看进程: 方式一: ps-ef|grep端口号/名称 方式二: netstat-apn|grep端口号/名称杀死进程: kill-9PID使用vi或vim命令打开、关闭、保存文件1、vi&vim有两种工作模式:​ (1)命令模式:接受、执行vi&vim操作命令的模式,打开文件后的默认模式;​ (…

    2022年4月9日
    35
  • 小说和漫画

    小说和漫画武侠金庸系列梁羽生系列古龙系列黄易系列卧龙生系列马荣成风云系列无忧公主萧逸奇侠杨小邪李凉神偷小千李凉天龙卷高庸剑魔独孤求败令狐庸金菊四绝曹若冰霸海心香东方英黄

    2022年7月3日
    44
  • navicat15激活码【永久激活】

    (navicat15激活码)2021最新分享一个能用的的激活码出来,希望能帮到需要激活的朋友。目前这个是能用的,但是用的人多了之后也会失效,会不定时更新的,大家持续关注此网站~IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.html…

    2022年3月22日
    891
  • Windows7 64位系统搭建Cocos2d-x 2.2.1最新版以及Android交叉编译环境(具体教程)

    Windows7 64位系统搭建Cocos2d-x 2.2.1最新版以及Android交叉编译环境(具体教程)

    2021年11月30日
    41
  • linux常用命令vi 退出_vi命令退出

    linux常用命令vi 退出_vi命令退出进入编辑模式,按o进行编辑编辑结束,按ESC键跳到命令模式,然后输入退出命令::w保存文件但不退出vi编辑:w!强制保存,不退出vi编辑:wfile将修改另存到file中,不退出vi编辑:wq保存文件并退出vi编辑:wq!强制保存文件并退出vi编辑q:不保存文件并退出vi编辑:q!不保存文件并强制退出vi编辑:e!放弃所有修改,从上次保…

    2022年9月30日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号