首页 > 其他分享 >constexpr学习

constexpr学习

时间:2023-05-25 09:33:54浏览次数:35  
标签:sz 常量 int 学习 constexpr 表达式 函数

constexptr和常量表达式
常量表达式是指值不会改变并且在编译过程中就能得到计算结果的表达式。

编译过程中得到计算结果。

字面值属于常量表达式,用常量表达式初始化的const对象也是常量表达式。

一个对象(或表达式)是不是常量表达式由它的数据类型和初始值共同决定。

(注意!!!)对于这条语句:const int sz = get_size();,sz本身是常量,但它的具体值直到运行时才能获得,不是常量表达式。
#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
const int max_files = 20; //max_files是常量表达式
const int limit = max_files + 1; //limit是常量表达式
int staff_size = 27; //staff_size不是常量表达式,数据类型只是普通类型而非常量类型
const int sz = get_size(); //重要!!!sz本身是常量,但它的具体值直到运行时才能获得,不是常量表达式
}
1
2
3
4
5
6
7
8
9
10
constexpr变量
在一个复杂的系统中,很难分辨一个初始值到底是不是常量表达式。当然可以定义一个const变量并把它的初始值设为我们认为的某个常量表达式,但在实际使用时,尽管要求如此却常常发现初始值并非常量表达式的情况(例如上述的const int sz = get_size(); 语句)。

C++11新标准规定,允许将变量声明为constexpr类型以便由编译器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须用常量表达式初始化:

#include<iostream>

using namespace std;

int main(int argc, char* argv[]) {
constexpr int max_files = 20; //20是常量表达式
constexpr int limit = max_files + 1; //max_files + 1是常量表达式
constexpr int sz = size(); //重要!!!只有当size是一个constexpr函数时,才是一条正确的声明语句
}
1
2
3
4
5
6
7
8
9
尽管不能使用普通函数作为constexpr变量的初始值,但可以通过constexpr函数(编译时就可以计算其结果)初始化constexpr变量。
constexpr函数
constexpr函数是指用于常量表达式的函数。

遵循以下规定:(1)函数的返回类型以及所有形参的类型都得是字面值类型;(2)函数体中必须只有一条return语句。

#include<iostream>

using namespace std;

constexpr int new_sz() {
return 42;
}

int main(int argc, char* argv[]) {
constexpr int foo = new_sz();
cout << foo << endl; //42
getchar();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
分析:我们把new_sz定义成无参的constexpr函数。因为编译器能在程序编译时验证new_sz函数返回的是常量表达式,所以可以用new_sz函数初始化constexpr类型的变量foo。

执行该初始化任务时,编译器把对constexpr函数的调用替换成其结果值。为了在编译过程中随时展开,constexpr函数被隐式地指定为内联函数。

constexpr函数体内也可以含有其他语句,只要这些语句在运行时不执行任何操作就行(求解答?)。例如,constexpr函数中可以有空语句、类型别名以及using声明。

constexpr int size() { //返回值类型为字面值类型
; //空语句
using In = int; //using声明
typedef int INT; //类型别名
return 10;
}

1
2
3
4
5
6
7
我们允许constexpr函数的返回值并非一个常量。当scale的实参是常量表达式,它的返回值也是常量表达式,反之则不然:
#include<iostream>

using namespace std;

constexpr int size() {
;
using namespace std;
typedef int INT;
return 10;
}

constexpr int new_sz() {
return 42;
}

//如果arg是常量表达式,则scale(arg)也是常量表达式
constexpr size_t scale(size_t cnt) {
return new_sz()*cnt;
}

int main(int argc, char* argv[]) {
int arr[scale(2)]; //正确
//int i = 2;
//int arr2[scale(i)]; //错误:scale(i)不是常量表达式
const int j = 2;
int arr3[scale(j)]; //正确
getchar();
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
把内联函数和constexpr函数放在头文件中:

和其他函数不一样,内联函数和constexpr函数可以在程序中多次定义。毕竟,编译器要想展开函数仅有函数声明是不够的,还需要函数的定义。不过,对于某个给定的内联函数或者constexpr函数来说,它的多个定义必须完全一致。基于这个原因,内联函数和constexpr函数通常定义在头文件中。
指针和constexpr
在constexpr声明中如果定义了一个指针,限定符constexpr仅对指针有效,与指针所指的对象无关:
const int *p = nullptr; //p是一个指向整型常量的指针
constexpr int *q = nullptr; //q是一个指向整型的常量指针
1
2
分析:p和q的类型相差甚远,p是一个指向常量的指针,q是一个常量指针,其中关键在于constexpr把它所定义的对象置为顶层const。
————————————————
版权声明:本文为CSDN博主「傻月菇凉」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40087851/article/details/82754189

标签:sz,常量,int,学习,constexpr,表达式,函数
From: https://www.cnblogs.com/im18620660608/p/17430209.html

相关文章

  • Zookeeper学习大纲
    ZooKeeper学习大纲ZooKeeper应用及原理解析Zookeeper介绍什么是ZookeeperZookeeper的应用场景搭建Zookeeper服务器zoo.cfg配置文件说明Zookeeper服务器的操作命令Zookeeper内部的数据模型zk是如何保存数据zk中的znode是什么样的结构zk中节点znode的类型zk的数......
  • C++11 constexpr:验证是否为常量表达式(长篇神文)
    constexpr是C++11标准新引入的关键字,不过在讲解其具体用法和功能之前,读者需要先搞清楚C++常量表达式的含义。 所谓常量表达式,指的就是由多个(≥1)常量组成的表达式。换句话说,如果表达式中的成员都是常量,那么该表达式就是一个常量表达式。这也意味着,常量表达式一旦确定,其值......
  • 这可能是最全面的Java学习路线了
    大家好,我是大彬~我本科学的不是计算机,大四开始自学Java,并且拿到了几个互联网中大厂的offer。在学习Java这方面还是比较有经验的,下面我来分享下我整理的Java自学路线。在这里也提醒学弟学妹们,要尽早确定以后的方向,读研还是工作,找工作的话,也要尽快确定工作岗位,想转行的,需要花更多......
  • YOLOv5s训练学习记录 - test
    armorFinder_ROS2YOLOv5s训练学习记录:训练、获取模型YOLOv5初级使用教程下载yolov5git上下载Yolov5并调通测试代码数据集准备与文件夹结构这里我使用的是之前提供的装甲板数据集'RM_train_data'这个和原本提供的'RM_train_data'不太一样,需要改成下边的样子├─images│......
  • ebpf 单行程序学习
    ebpf单行程序学习背景公司方神借给我一本:《BPF之巅:洞悉linux系统和应用性能》纸质书拿回家晚上在沙发上看了几天。感觉书很厚看的不是很系统。仅能凭自己的感觉总结一下这些天的读书感悟。本来计划是2023年的春节7天长假系统的学习ebpf但是因为学习Linux内核参数耽......
  • 我是如何学习软件工程的
    软件工程是一个庞大且不断演化的领域,涉及许多创新。虽然如此,大多数技术——如果不是全部——在软件工程中往往最终汇聚为几个基本原则。工程师更好地学习软件工程的方法是学习软件工程的基础知识,而不是那些不断变化的框架、语言或平台。即使学习基础知识也需要时间和努力。人们经......
  • 「学习笔记」略谈点分治
    点分治适合处理大规模的树上路径信息问题。引入给定一棵\(n\)个点树和一个整数\(k\),求树上两点间的距离小于等于\(k\)的点对有多少。对于这个题,如果我们进行\(O_{n^3}\)搜索,那只要\(n\)一大,铁定超时。所以,我们要用一个更优秀的解法,这就是我们的点分治。淀粉质可......
  • *【学习笔记】(9) 分块
    分块思想引用一下oi-wiki的话:分块的基本思想是:通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。数列/序列分块引入#6280.数列分块入门4给定一长度为$n$的数列,有\(n\)次操作。操作分为两种:区间加,查询区间......
  • 【学习笔记】(15) Kruskal 重构树
    前置知识:kruskal求最小生成树,倍增。1.算法简介以下所有讨论基于最小生成树。在Kruskal求最小生成树的过程:将所有边按照边权排序,若当前边\((u,v)\)两端不连通,则往生成树边集\(E\)中加入\((u,v)\)并连接\(u,v\)。使用并查集维护连通性。如果能用某种结构描述每条边......
  • GitlabCI学习笔记之三:GitLabRunner pipeline语法之tags allow_faillure when retry ti
    1.tags用于从允许运行该项目的所有Runner列表中选择特定的Runner,在Runner注册期间,您可以指定Runner的标签。tags可让您使用指定了标签的runner来运行作业,此runner具有ruby和postgres标签。示例给定带有osx标签的OSXRunner和带有windows标签的WindowsRunner,以下作业将在......