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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C语言 最长回文子串[通俗易懂]

    C语言 最长回文子串[通俗易懂]描述:输入一个字符串,求其中最长回文子串。子串的含义是:在字符串中连续出现得字符串片段。回文的含义是,正着看和倒着看是相同的,如abba何abbebba。在判断时要求忽略所有的标点和空格,且忽略大小写。但输出时按原样输出(首尾不要输出多余的字符串).输入字符串长度大于等于1小于等于5000.且单独占一行。输入:输入一行字符串。输出:输出所要求的回文子串。样例输入:L…

    2022年6月7日
    55
  • Asp.net Web.Config – 配置元素customErrors

    Asp.net Web.Config – 配置元素customErrorsAsp.netWeb.Config-配置元素customErrors Asp.net配置文件的配置方式,其实在MSDN里面是写得最清楚的了。可惜之前一直未曾了解到MSDN的强大。  先贴个地址:http://msdn.microsoft.com/zh-cn/library/dayb112d(v=vs.80).aspx,然后逐个分析。我希望自己能够从头到尾认真学完这系列东西。为了不至于让自己太早放弃,我决定从自己用过的配置文件学起,然后逐渐接触那些比较生疏,和少用的。一、customErro

    2022年7月16日
    19
  • 整除计算器_0 整除

    整除计算器_0 整除原题链接这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1、11、111、1111等。传说任何一个光棍都能被一个不以5结尾的奇数整除。比如,111111就可以被13整除。 现在,你的程序要读入一个整数x,这个整数一定是奇数并且不以5结尾。然后,经过计算,输出两个数字:第一个数字s,表示x乘以s是一个光棍,第二个数字n是这个光棍的位数。这样的解当然不是唯一的,题目要求你输出最小的解。提示:一个显然的办法是逐渐增加光棍的位数,直到可以整除x为止。但难点在于,s可能是个非常大的数 ——

    2022年8月8日
    3
  • HTTPS 和 SSL/TLS 协议:密钥交换(密钥协商)算法及其原理

    HTTPS 和 SSL/TLS 协议:密钥交换(密钥协商)算法及其原理

    2021年6月12日
    155
  • 使用CEfSharp之旅(6)拦截网络请求 截取get post response返回「建议收藏」

    使用CEfSharp之旅(6)拦截网络请求 截取get post response返回「建议收藏」主要是继承实现Cefsharp的IRquestHandler对象,废话不多说上代码:publicclassrequest:IRequestHandler{publiceventAction<string>msg;publiceventAction<string,object>…

    2025年11月29日
    10
  • layui的layer弹出层和form表单

    layui的layer弹出层和form表单文章目录弹出层layerform表单增删改查所有代码如果想用layui来完成增删改查,那么要会用弹出层和form表单这两个组件是必须的,所以今天就来介绍一些如何用layui完成基本的增删改查弹出层layer因为layui的特性,每次不管使用哪个组件,都要先把它的模块加载出来比如我要用layer和form那么就需要先这样定义,你的操作都是在这个里面进行,当然页可以一次性加载所有模块,详情…

    2022年7月13日
    20

发表回复

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

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