3、const与constexpr
初遇到constexpr真的是有点懵比,看了很多博客也没看懂,不知道是我太笨,还是别人写的太深奥?总之经过一番折腾算是入门了。一下是我个人总结,有不对的地方望指出。
一、学习const与constexpr必须要先知道一下几个概念:
1、constexpr是constant expression的缩写。顾名思义“常量 表达式”
2、何为常量表达式(constant expression):是指由编译器求值的表达式。
在这里在解释一下编译器求值概念:编译系统由预处理器、编译器、汇编器、连接器四部分组成
一个源文件到一个可执行文件要经过这四部分,所谓的编译器求值指的就是第二部分编译器部分,
二、 C++中的const与constexpr都是与“常量”有关的两个概念。
1、C++中的const兼容了C语言中的const。
(1)C语言中的const:
① 编译器可以把声明带 const 限定类型的对象放到只读内存中。
② const 语义仅应用到左值表达式
③ 指代 const 限定类型对象的左值表达式,和指代拥有至少一个 const 限定类型成员(包含为聚合体或联合体所递归含有的成员)的结构体或联合体的左值表达式,不是可修改左值。具体而言,它们不可赋值:
const int n = 1; // const 类型对象
n = 2; // 错误: n 的类型为 const 限定
int x = 2; // 无限定类型对下
const int* p = &x;
*p = 3; // 错误:左值 *p 的类型为 const 限定
struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2};
s1 = s2; // 错误: s1 的类型无限定,但它有 const 成员
const 限定的结构体或联合体类型的成员,取得它所属类型的限定版本(在用 . 运算符或 -> 运算符访问时)。
struct s { int i; const int ci; } s;
// s.i 的类型为 int , s.ci 的类型为 const int
const struct s cs;
// cs.i 和 cs.ci 的类型都是 const int
若以 const 类型限定符声明数组类型(通过使用 typedef ),则数组类型无 const 限定,但其元素类型有。若以 const 类型限定符声明函数类型(通过使用 typedef ),则行为未定义。
typedef int A[2][3];
const A a = {{4, 5, 6}, {7, 8, 9}}; // const int 的数组的数组
int* pi = a[0]; // 错误: a[0] 拥有 const int* 类型
指向非 const 类型的指针能隐式转换成指向同一或兼容类型的 const 限定版本的指针。能用转型表达式进行逆向转换。
int* p = 0;
const int* cp = p; // OK :添加限定符( int 到 const int )
p = cp; // 错误:舍弃限定符( const int 到 int )
p = (int*)cp; // OK :转型
注意指向指向 T 指针的指针不可转换为指向指向 const T 指针的指针;对于要兼容的二个类型,其限定必须等同。
char *p = 0;
const char **cpp = &p; // 错误: char* 与 const char* 不是兼容类型
char * const *pcp = &p; // OK :添加限定符( char * 到 char *const )
2、constexpre的用法:
constexpr- 指定变量或函数的值可在常量表达式中出现解释
constexpr说明符声明可以在编译时求得函数或变量的值。然后这些变量和函数(若给定了合适的函数实参)即可用于仅允许编译时常量表达式之处。用于对象或非静态成员函数 (C++14 前)声明的 constexpr 说明符蕴含 const。用于函数声明的 constexpr说明符或 static 成员变量 (C++17 起)蕴含 inline。若函数或函数模板的任何声明拥有constexpr说明符,则每个声明必须都含有该说明符。constexpr 变量必须满足下列要求:
- 其类型必须是字面类型 (LiteralType)。
- 它必须被立即初始化
- 其初始化的全表达式,包括所有隐式转换、构造函数调用等,都必须是常量表达式
constexpr 函数必须满足下列要求:
|
(C++20 前) |
|
(C++14 前) | ||
(=default; 或 =delete; 的函数体不含任何上述内容。) |
(C++14 起) |
- 它必须非虚
(C++20 前) - 它必须不是协程
(C++20 起) - 其返回类型(若存在)必须是字面类型 (LiteralType)
- 其每个参数都必须是字面类型 (LiteralType)
- 对于构造函数与析构函数 (C++20 起),该类必须无虚基类
- 至少存在一组实参值,使得函数的一个调用为核心常量表达式的被求值的子表达式(对于构造函数为足以用于常量初始化器)(C++14 起)。不要求对这点的诊断。
3、const与constexpr的更多相关文章
- 【C++】C++中const与constexpr的比较
先说结论相同点:const和consexpr都是用来定义常量的.不同点:const声明的常量,初始值引用的对象不一定是一个常量:constexpr声明的常量,初始值一定是常量表达式. constexp ...
- C++总结:C++中的const和constexpr
C++中的const可用于修饰变量.函数,且在不同的地方有着不同的含义,现总结如下. const的语义 C++中的const的目的是通过编译器来保证对象的常量性,强制编译器将所有可能违背const对象 ...
- const 和 constexpr
在C++中,const 这个关键字用法非常灵活,导致我总会搞不清作用是干啥的.灵活使用const会大大改善程序. const 是C++的一种类型修饰符,是不可改变的不能被更新的. 1.const 修饰 ...
- C++中const与constexpr区别
对于对象来说 const指的是编译期常量和运行时常量,两者并没有区分 constexpr特指编译期常量 对于函数来说 const可以修饰类的成员函数,被修饰的函数在执行期间不会改变对象的值. clas ...
- const与constexpr
关于const型数据,谭浩强老爷子这么总结道: Time const t; //t是常对象,其值在任何情况下都不能改变 void Time::fun()const; //fun是Time类中的常成员函 ...
- C++ const和constexpr
const expression , 常量表达式 , 在<C++ Primer>的定义:值不会改变并且在编译过程就能得到计算结果的表达式. 它要求两点:值不会改变,编译过程得到结果. ...
- C++常量表达式、const、constexpr(C++11新增)的区别
常量表达式是指值不会改变且在编译过程中就能够得到计算结果的表达式,能在编译时求值的表达式. 程序先编译再运行: 在编译阶段, 编译器将在编译过程中把用到该常量的地方都全都替换为 常量的值. 但是常量 ...
- [c++] constexpr and literal class
稀奇古怪的新特性,菜鸟在此啄上一啄. 1. When should literal classes be used in C++? 2. int i; // not constant const ...
- 概览C++之const
1.C语言中const与 C++中的const void main() { const int a = 10; int *p = (int*)&a; *p = 20; printf(" ...
随机推荐
- 浅谈CC攻击原理与防范
概念 CC攻击的原理就是攻击者控制某些主机不停地发大量数据包给对方服务器造成服务器资源耗尽,一直到宕机崩溃.CC主要是用来攻击页面的,每个人都有这样的体验:当一个网页访问的人数特别多的 ...
- 20191225--python学习第二天笔记(补)
1.内容回顾 学习计算机基础 安装解释器 2.语法 print/input 整型 int/字符串 str/布尔类型 boolen 条件语句 and运算符 变量 3.练习 评分规则:用户输入成绩,根据成 ...
- Spark作业执行流程源码解析
目录 相关概念 概述 源码解析 作业提交 划分&提交调度阶段 提交任务 执行任务 结果处理 Reference 本文梳理一下Spark作业执行的流程. Spark作业和任务调度系统是其核心,通 ...
- [Redis-CentOS7]Redis安装(-)
系统环境 CentOS Linux release 7.7.1908 (Core) yum安装 yum install redis Loaded plugins: fastestmirror Load ...
- windows下python3使用pip安装scrapy提示安装失败
我的环境: python3.6, win10, 原因:不能成功安装twisted,因为twisted与高版本的python有兼容问题. 解决:1,先下载twisted二进制文 ...
- 作为一个Java工程师,你应该要知道SPI机制
什么是 SPI SPI是Service Provider Interface的简称,是JDK默认提供的一种将接口和实现类进行分离的机制.这种机制能将接口和实现进行解耦,大大提升系统的可扩展性. SPI ...
- 01-Flink运行架构
1.flink运行时的组件 Flink 运行时架构主要包括四个不同的组件,它们会在运行流处理应用程序时协同工作: 作业管理器(JobManager).资源管理器(ResourceManager). ...
- 解决visual studio 2013编译过程中存在的无法打开kernel.lib问题
1. 出现此类问题的原因 由于原visual studio文件中的安装中出现问题,所以原有的SDK(soft development kits)文件出现缺失: 2. 解决方法1 重新下载SDK工具,安 ...
- .Net Core程序最终只产生1个exe
1.用VS新建一个.Net Core 命令行程序,程序里面写什么都行,我的是这样的 2.打开程序包控制台,或者使用PowerShell等可以执行dotnet命令的工具,把你的.Net 程序发布(编译) ...
- Charles抓包工具的破解以及使用
一.破解 官网下载Charles 下载Charles.jar ,然后按照后在Charles→lib中替换掉Charles.jar 链接:https://pan.baidu.com/s/1XZ-aZI5 ...