北京城乡与建设厅官方网站查询,低价虚拟主机,800元建网站,wordpress如何做页面模板下载地址1. constexpr#xff1a;常量表达式
所谓常量表达式,指的就是由多个(≥1)常量组成的表达式。换句话说,如果表达式中的成员都是常量,那么该表达式就是一个常量表达式。这也意味着#xff0c;常量表达式一旦确定#xff0c;其值将无法修改。 实际开发中#xff0c;我们经常会…1. constexpr常量表达式
所谓常量表达式,指的就是由多个(≥1)常量组成的表达式。换句话说,如果表达式中的成员都是常量,那么该表达式就是一个常量表达式。这也意味着常量表达式一旦确定其值将无法修改。 实际开发中我们经常会用到常量表达式。以定义数组为例数组的长度就必须是一个常量表达式
// 1)
int url[10];//正确
// 2)
int url[6 4];//正确
// 3)
int length 6;
int url[length];//错误length是变量
上述代码演示了 3 种定义 url 数组的方式其中第 1、2 种定义 url 数组时长度分别为 10 和 64显然它们都是常量表达式可以用于表示数组的长度第 3 种 url 数组的长度为 length它是变量而非常量因此不是一个常量表达式无法用于表示数组的长度。
常量表达式的应用场景还有很多比如匿名枚举、switch-case 结构中的 case 表达式等感兴趣的读者可自行编码测试这里不再过多举例。
我们知道C 程序的执行过程大致要经历编译、链接、运行这 3 个阶段。值得一提的是常量表达式和非常量表达式的计算时机不同非常量表达式只能在程序运行阶段计算出结果而常量表达式的计算往往发生在程序的编译阶段这可以极大提高程序的执行效率因为表达式只需要在编译阶段计算一次节省了每次程序运行时都需要计算一次的时间。
对于用 C 编写的程序性能往往是永恒的追求。那么在实际开发中如何才能判定一个表达式是否为常量表达式进而获得在编译阶段即可执行的“特权”呢除了人为判定外C11 标准还提供有 constexpr 关键字。
constexpr 关键字的功能是使指定的常量表达式获得在程序编译阶段计算出结果的能力而不必等到程序运行阶段。C 11 标准中constexpr 可用于修饰普通变量、函数包括模板函数以及类的构造函数。 注意获得在编译阶段计算出结果的能力并不代表 constexpr修饰的表达式一定会在程序编译阶段被执行具体的计算时机还是编译器说了算。 1.1 constexpr修饰普通变量
C11 标准中定义变量时可以用constexpr 修饰从而使该变量获得在编译阶段即可计算出结果的能力。
注意使用 constexpr 修改普通变量时变量必须经过初始化且初始值必须是一个常量表达式。举个例子
#include iostream
using namespace std;int main()
{constexpr int num 1 2 3;int url[num] {1,2,3,4,5,6};couts url[1] endl;return 0;
}程序执行结果为
2读者可尝试将 constexpr 删除此时编译器会提示“url[num] 定义中 num 不可用作常量”。
可以看到程序第 6 行使用 constexpr 修饰 num 变量同时将 “123” 这个常量表达式赋值给 num。由此编译器就可以在编译时期对 num 这个表达式进行计算因为 num 可以作为定义数组时的长度。
有读者可能发现将此示例程序中的 constexpr 用const关键字替换也可以正常执行这是因为 num 的定义同时满足“num 是 const 常量且使用常量表达式为其初始化”这 2 个条件由此编译器会认定 num 是一个常量表达式。
另外需要重点提出的是当常量表达式中包含浮点数时考虑到程序编译和运行所在的系统环境可能不同常量表达式在编译阶段和运行阶段计算出的结果精度很可能会受到影响因此 C11 标准规定浮点常量表达式在编译阶段计算的精度要至少等于或者高于运行阶段计算出的精度。
1.2 constexpr修饰函数
constexpr 还可以用于修饰函数的返回值这样的函数又称为“常量表达式函数”。
注意constexpr 并非可以修改任意函数的返回值。换句话说一个函数要想成为常量表达式函数必须满足如下 4 个条件 1) 该函数必须有返回值即函数的返回值类型不能是 void。 举个例子
constexpr void display() {//函数体
}像上面这样定义的返回值类型为 void 的函数不属于常量表达式函数。原因很简单因为通过类似的函数根本无法获得一个常量。 2) 整个函数的函数体中除了可以包含 using 指令、typedef 语句以及 static_assert 断言外只能包含一条 return 返回语句。 举个例子
constexpr int display(int x) {int ret 1 2 x;return ret;
}注意这个函数是无法通过编译的因为该函数的返回值用 constexpr 修饰但函数内部包含多条语句。 如下是正确的定义 display() 常量表达式函数的写法
constexpr int display(int x) {//可以添加 using 执行、typedef 语句以及 static_assert 断言return 1 2 x;
}可以看到display() 函数的返回值是用 constexpr 修饰的 int 类型值且该函数的函数体中只包含一个return语句。 3)return 返回的表达式必须是常量表达式。 举个例子
#include iostream
using namespace std;int num 3;
constexpr int display(int x){return num x;
}
int main()
{//调用常量表达式函数int a[display(3)] { 1,2,3,4 };return 0;
}该程序无法通过编译编译器报“display(3) 的结果不是常量”的异常。
常量表达式函数的返回值必须是常量表达式的原因很简单如果想在程序编译阶段获得某个函数返回的常量则该函数的 return 语句中就不能包含程序运行阶段才能确定值的变量。
注意在常量表达式函数的 return 语句中不能包含赋值的操作例如 return x1 在常量表达式函数中不允许的。另外用 constexpr 修改函数时函数本身也是支持递归的感兴趣的读者可自行尝试编码测试。
4) 函数在使用之前必须有对应的定义语句。我们知道函数的使用分为“声明”和“定义”两部分普通的函数调用只需要提前写好该函数的声明部分即可函数的定义部分可以放在调用位置之后甚至其它文件中但常量表达式函数在使用前必须要有该函数的定义。 举个例子
#include iostream
using namespace std;//普通函数的声明
int noconst_dis(int x);
//常量表达式函数的声明
constexpr int display(int x);//常量表达式函数的定义
constexpr int display(int x){return 1 2 x;
}
int main()
{//调用常量表达式函数int a[display(3)] { 1,2,3,4 };cout a[2] endl;//调用普通函数cout noconst_dis(3) endl;return 0;
}
//普通函数的定义
int noconst_dis(int x) {return 1 2 x;
}
程序执行结果为
3
6读者可自行将 display() 常量表达式函数的定义调整到 main() 函数之后查看编译器的报错信息。可以看到普通函数在调用时只需要保证调用位置之前有相应的声明即可而常量表达式函数则不同调用位置之前必须要有该函数的定义否则会导致程序编译失败。
1.3 constexpr修饰类的构造函数
对于 C 内置类型的数据可以直接用 constexpr 修饰但如果是自定义的数据类型用 struct 或者 class 实现直接用 constexpr 修饰是不行的。
举个例子
#include iostream
using namespace std;//自定义类型的定义
constexpr struct myType {const char* name;int age;//其它结构体成员
};int main()
{constexpr struct myType mt{ zhangsan, 10 };cout mt.name mt.age endl;return 0;
}此程序是无法通过编译的编译器会抛出“constexpr不能修饰自定义类型”的异常。
当我们想自定义一个可产生常量的类型时正确的做法是在该类型的内部添加一个常量构造函数。例如修改上面的错误示例如下
#include iostream
using namespace std;
//自定义类型的定义
struct myType {constexpr myType(char *name,int age):name(name),age(age){};const char* name;int age;//其它结构体成员
};
int main()
{constexpr struct myType mt { zhangsan, 10 };cout mt.name mt.age endl;return 0;
}程序执行结果为
zhangsan 10可以看到在 myType 结构体中自定义有一个构造函数借助此函数用 constexpr 修饰的 myType 类型的mt常量即可通过编译。
注意constexpr 修饰类的构造函数时要求该构造函数的函数体必须为空且采用初始化列表的方式为各个成员赋值时必须使用常量表达式。
前面提到constexpr 可用于修饰函数而类中的成员方法完全可以看做是“位于类这个命名空间中的函数”所以 constexpr 也可以修饰类中的成员函数只不过此函数必须满足前面提到的 4 个条件。
举个例子
#include iostream
using namespace std;//自定义类型的定义
class myType {
public:constexpr myType(const char *name,int age):name(name),age(age){};constexpr const char * getname(){return name;}constexpr int getage(){return age;}
private:const char* name;int age;//其它结构体成员
};int main()
{constexpr struct myType mt { zhangsan, 10 };constexpr const char * name mt.getname();constexpr int age mt.getage();cout name age endl;return 0;
}程序执行结果为
zhangsan 10注意C11 标准中不支持用 constexpr 修饰带有 virtual 的成员方法。
1.4 constexpr修饰模板函数
C11 语法中constexpr 可以修饰模板函数但由于模板中类型的不确定性因此模板函数实例化后的函数是否符合常量表达式函数的要求也是不确定的。
针对这种情况下C11 标准规定如果 constexpr 修饰的模板函数实例化结果不满足常量表达式函数的要求则 constexpr 会被自动忽略即该函数就等同于一个普通函数。
举个例子
#include iostream
using namespace std;//自定义类型的定义
struct myType {const char* name;int age;//其它结构体成员
};
//模板函数
templatetypename T
constexpr T dispaly(T t){return t;
}int main()
{struct myType stu{zhangsan,10};//普通函数struct myType ret dispaly(stu);cout ret.name ret.age endl;//常量表达式函数constexpr int ret1 dispaly(10);cout ret1 endl;return 0;
}程序执行结果为
zhangsan 10
10可以看到示例程序中定义了一个模板函数 display()但由于其返回值类型未定因此在实例化之前无法判断其是否符合常量表达式函数的要求.
2. const与constexpr区别
一些读者在学习过程中经常会把 const 和 constexpr 搞混不知道什么时候用 const什么时候用 constexpr。本节就带领大家对 const 和 constexpr 做系统地区分。
有关 constexpr 的功能和用法您可以阅读《C11 constexpr》一节。
我们知道constexpr 是 C 11 标准新添加的关键字在此之前C 98/03标准只有const关键字其在实际使用中经常会表现出两种不同的语义。举个例子
#include iostream
#include array
using namespace std;void dis_1(const int x){//错误x是只读的变量array int,x myarr{1,2,3,4,5};cout myarr[1] endl;
}void dis_2(){const int x 5;array int,x myarr{1,2,3,4,5};cout myarr[1] endl;
}int main()
{dis_1(5);dis_2();
}
可以看到dis_1() 和 dis_2() 函数中都包含一个 const int x但 dis_1() 函数中的 x 无法完成初始化 array 容器的任务而 dis_2() 函数中的 x 却可以。
这是因为dis_1() 函数中的“const int x”只是想强调 x 是一个只读的变量其本质仍为变量无法用来初始化 array 容器而 dis_2() 函数中的“const int x”表明 x 是一个只读变量的同时x 还是一个值为 5 的常量所以可以用来初始化array容器。
C 11标准中为了解决const关键字的双重语义问题保留了const表示“只读”的语义而将“常量”的语义划分给了新添加的 constexpr 关键字。因此 C11 标准中建议将const和 constexpr 的功能区分开即凡是表达“只读”语义的场景都使用 const表达“常量”语义的场景都使用 constexpr。
在上面的实例程序中dis_2() 函数中使用 const int x 是不规范的应使用 constexpr 关键字。
有读者可能会问“只读”不就意味着其不能被修改吗答案是否定的“只读”和“不允许被修改”之间并没有必然的联系举个例子
#include iostream
using namespace std;int main()
{int a 10;const int con_b a;cout con_b endl;a 20;cout con_b endl;
}
程序执行结果为
10
20可以看到程序中用 const 修饰了 con_b 变量表示该变量“只读”即无法通过变量自身去修改自己的值。但这并不意味着 con_b 的值不能借助其它变量间接改变通过改变 a 的值就可以使con_b的值发生变化。 在大部分实际场景中const 和 constexpr 是可以混用的例如
const int a 5 4;
constexpr int a 5 4;它们是完全等价的都可以在程序的编译阶段计算出结果。但在某些场景中必须明确使用 constexpr例如
#include iostream
#include array
using namespace std;constexpr int sqr1(int arg){return arg*arg;
}const int sqr2(int arg){return arg*arg;
}int main()
{arrayint,sqr1(10) mylist1;//可以因为sqr1时constexpr函数arrayint,sqr2(10) mylist1;//不可以因为sqr2不是constexpr函数return 0;
}其中因为 sqr2() 函数的返回值仅有const修饰而没有用更明确的 constexpr 修饰导致其无法用于初始化 array 容器只有常量才能初始化array容器。
总的来说在 C 11 标准中const 用于为修饰的变量添加“只读”属性而 constexpr 关键字则用于指明其后是一个常量或者常量表达式编译器在编译程序时可以顺带将其结果计算出来而无需等到程序运行阶段这样的优化极大地提高了程序的执行效率。
参考 https://blog.csdn.net/lemonxiaoxiao/article/details/128344695 文章转载自: http://www.morning.nqyfm.cn.gov.cn.nqyfm.cn http://www.morning.crkmm.cn.gov.cn.crkmm.cn http://www.morning.ygwbg.cn.gov.cn.ygwbg.cn http://www.morning.wcczg.cn.gov.cn.wcczg.cn http://www.morning.yqpck.cn.gov.cn.yqpck.cn http://www.morning.yrjxr.cn.gov.cn.yrjxr.cn http://www.morning.hmsong.com.gov.cn.hmsong.com http://www.morning.yskhj.cn.gov.cn.yskhj.cn http://www.morning.ryjl.cn.gov.cn.ryjl.cn http://www.morning.nqcts.cn.gov.cn.nqcts.cn http://www.morning.lpmjr.cn.gov.cn.lpmjr.cn http://www.morning.kfcz.cn.gov.cn.kfcz.cn http://www.morning.wyzby.cn.gov.cn.wyzby.cn http://www.morning.rcbdn.cn.gov.cn.rcbdn.cn http://www.morning.qbtj.cn.gov.cn.qbtj.cn http://www.morning.vvdifactory.com.gov.cn.vvdifactory.com http://www.morning.qkdcb.cn.gov.cn.qkdcb.cn http://www.morning.mngyb.cn.gov.cn.mngyb.cn http://www.morning.dzrcj.cn.gov.cn.dzrcj.cn http://www.morning.hengqilan.cn.gov.cn.hengqilan.cn http://www.morning.cbynh.cn.gov.cn.cbynh.cn http://www.morning.jghty.cn.gov.cn.jghty.cn http://www.morning.jzyfy.cn.gov.cn.jzyfy.cn http://www.morning.xqgtd.cn.gov.cn.xqgtd.cn http://www.morning.knmby.cn.gov.cn.knmby.cn http://www.morning.hlyfn.cn.gov.cn.hlyfn.cn http://www.morning.xjpnq.cn.gov.cn.xjpnq.cn http://www.morning.wngpq.cn.gov.cn.wngpq.cn http://www.morning.nrbcx.cn.gov.cn.nrbcx.cn http://www.morning.ndtmz.cn.gov.cn.ndtmz.cn http://www.morning.pbsfq.cn.gov.cn.pbsfq.cn http://www.morning.rnmyw.cn.gov.cn.rnmyw.cn http://www.morning.bslkt.cn.gov.cn.bslkt.cn http://www.morning.dspqc.cn.gov.cn.dspqc.cn http://www.morning.rnpnn.cn.gov.cn.rnpnn.cn http://www.morning.wfmqc.cn.gov.cn.wfmqc.cn http://www.morning.znlhc.cn.gov.cn.znlhc.cn http://www.morning.xcxj.cn.gov.cn.xcxj.cn http://www.morning.whothehellami.com.gov.cn.whothehellami.com http://www.morning.jtkfm.cn.gov.cn.jtkfm.cn http://www.morning.rbgqn.cn.gov.cn.rbgqn.cn http://www.morning.shnqh.cn.gov.cn.shnqh.cn http://www.morning.smxyw.cn.gov.cn.smxyw.cn http://www.morning.yrqb.cn.gov.cn.yrqb.cn http://www.morning.rxgnn.cn.gov.cn.rxgnn.cn http://www.morning.kxyqy.cn.gov.cn.kxyqy.cn http://www.morning.kmwbq.cn.gov.cn.kmwbq.cn http://www.morning.bxqpl.cn.gov.cn.bxqpl.cn http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.kfyjh.cn.gov.cn.kfyjh.cn http://www.morning.shinezoneserver.com.gov.cn.shinezoneserver.com http://www.morning.qnbgk.cn.gov.cn.qnbgk.cn http://www.morning.ldfcb.cn.gov.cn.ldfcb.cn http://www.morning.yqzyp.cn.gov.cn.yqzyp.cn http://www.morning.ffbp.cn.gov.cn.ffbp.cn http://www.morning.lxhny.cn.gov.cn.lxhny.cn http://www.morning.wyjpt.cn.gov.cn.wyjpt.cn http://www.morning.mpnff.cn.gov.cn.mpnff.cn http://www.morning.lrwsk.cn.gov.cn.lrwsk.cn http://www.morning.qnpyz.cn.gov.cn.qnpyz.cn http://www.morning.qjxkx.cn.gov.cn.qjxkx.cn http://www.morning.zhnpj.cn.gov.cn.zhnpj.cn http://www.morning.svtxeu.com.gov.cn.svtxeu.com http://www.morning.grwgw.cn.gov.cn.grwgw.cn http://www.morning.mxtjl.cn.gov.cn.mxtjl.cn http://www.morning.mflhr.cn.gov.cn.mflhr.cn http://www.morning.ljbm.cn.gov.cn.ljbm.cn http://www.morning.i-bins.com.gov.cn.i-bins.com http://www.morning.rnmyw.cn.gov.cn.rnmyw.cn http://www.morning.myzfz.com.gov.cn.myzfz.com http://www.morning.rqqlp.cn.gov.cn.rqqlp.cn http://www.morning.kqrql.cn.gov.cn.kqrql.cn http://www.morning.routalr.cn.gov.cn.routalr.cn http://www.morning.bnwlh.cn.gov.cn.bnwlh.cn http://www.morning.prmyx.cn.gov.cn.prmyx.cn http://www.morning.tqqfj.cn.gov.cn.tqqfj.cn http://www.morning.mnwb.cn.gov.cn.mnwb.cn http://www.morning.mkyxp.cn.gov.cn.mkyxp.cn http://www.morning.plchy.cn.gov.cn.plchy.cn http://www.morning.jtkfm.cn.gov.cn.jtkfm.cn