【C++】用constexpr,constinit,consteval让程序跑的快一点

news2024/11/18 7:35:22

从C++11加入constexpr关键字开始,到C++20又加入了consteval ,constinit ,有3个const打头的关键字

虽然是以const开头的,不过这3个关键字主要是指示在编译时候的动作,它们都是在编译时就已经被编译程序处理,并非在运行时被机器处理

下面逐一介绍

以下代码在cygwin gcc 11.4 cmake 3.25中调试通过

constexpr

constexpr是在C++11中加入的关键字,它可以使用在函数和变量上,可以让函数或者变量在编译期间直接算出结果
先看一段代码

#include <stdio.h>
int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    int r = sqr(2);
    printf("%d",r);
    return 0;
}

以上代码,调用sqr 计算2的平方

看汇编代码
在这里插入图片描述
上述代码每一步都执行了,包括赋值、调用sqr

然后在对sqr前和变量r前加上constexpr,再看使用constexpr修饰后的结果

#include <stdio.h>
constexpr int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    constexpr int r = sqr(2);
    printf("%d",r);
    return 0;
}

看汇编代码
在这里插入图片描述
可以看到,sqr并没有被调用,程序在运行前,就已经被编译程序直接计算出了2的平方为4

这就是constexpr的作用,包括constinit,consteval也是这个作用。

不过,这三个关键字,同样的,必须是程序在未运行前,就可以通过计算确定出的值
,只要输入一个已知的值,就一定可以计算出一个值,这样才能用

比如上例改为

constexpr int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    constexpr int r = sqr(x);
    printf("%d",r);
    return 0;
}

会报错

 error: ‘x’ is not a constant expression

应为r 被修饰为constexpr ,所以在编译是必须已经可以产生确定的值才行,而sqr传入x是没有办法算出确定的值的,因为X也不确定

同理,代码如下,将sqr的constexpr 去掉

#include <stdio.h>
int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    constexpr int r = sqr(2);
    printf("%d",r);
    return 0;
}

同样也会报错

 error: call to non-‘constexpr’ function ‘int sqr(int)’

因为r 是需要一个可以确认的值,但sqr并不是一个可以,立即执行的确认函数

但是反过来没有问题,把变量r前的constexpr 去掉 ,直接传入数值,或者传入一个变量都可以了

#include <stdio.h>
constexpr int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    int r = sqr(2);//sqr(x)
    printf("%d",r);
    return 0;
}

生成的汇编,就像一个函数调用了一样
在这里插入图片描述

下面,介绍一下constexpr 修饰变量的操作,有如下代码

int main(int x, char**) 
{   
    int a = 6;
    constexpr int r = a==6?1:2 ;
    printf("%d",r);
    return 0;
}

上述代码应为a不是常量,所以会报错

 the value of ‘a’ is not usable in a constant expression

原因也是应为a的不确定性导致

修改他的方法,有两种
把int a = 6改为const

const int a = 6

或者

constexpr int a = 6;

a变成不可修改的常量,r的值就可以被确定

其次,被constexpr 修饰的变量,是具有const属性的,不能被修改

int main(int x, char**) 
{   
    const int a = 6;
    constexpr int r = a==6?1:2 ;
    r = 3;
    printf("%d",r);
    return 0;
}

报错如下

 error: assignment of read-only variable ‘r’

consteval

constexpr可以使用在函数和变量上,consteval只能使用在函数上,强制为可以计算出结果的函数

上面介绍constexpr 时,如果变量不用constexpr修饰那么调用sqr时,可以传入变量,但是被consteval修饰的函数,就会报错了

#include <stdio.h>
consteval int sqr(int n)
{
    return n * n;
}
int main(int x, char**) 
{   
    int r = sqr(x);
    printf("%d",r);
    return 0;
}

错误

‘x’ is not a constant expression

这说明被consteval修饰的函数,必须一定要能即时计算才行,所以,要改为

int r = sqr(2);

才可以

constinit

和consteval一样,它也是强制在编译时产生结果的,只不过,consteval强制的是函数,constinit强制的变量

constexpr int sqr(int n)
{
    return n * n;
}
constinit int r = sqr(2);

int main(int x, char**) 
{   
    printf("%d",r);
    return 0;
}

以上代码可以顺利编译通过
但是如果,改为如下

int g =1;
constexpr int sqr(int n)
{
    return n * n;
}
constinit int r = sqr(g);

int main(int x, char**) 
{   
    printf("%d",r);
    return 0;
}

编译器将会产生相关两条错误

1.error: the value of 'g' is not usable in a constant expression
2.error: 'constinit' variable 'r' does not have a constant initializer

应为sqr传入了不是常量的数据,导致sqr不能判断出最终r是什么值
如果想让上例通过,需要将g改为常量

constexpr int g =1;
//const int g =1;

这两种都可以

因为constinit修饰的是静态或线程存储期的变量,所以,它不能在局部函数中出现,上例中,如果将

constinit int r = sqr(2);

移入main中会报错

int main(int x, char**) 
{   
    constinit int r = sqr(2);
    printf("%d",r);
    return 0;
}

错误如下

‘constinit’ can only be applied to a variable with static or thread storage duration

和constexpr修饰的变量不一样,constinit修饰的变量只做强制运算,并不会产生const 变量,所以constinit修饰的变量是可以修改的

constexpr int sqr(int n)
{
    return n * n;
}
constinit int r = sqr(2);
int main(int x, char**) 
{   
    r = 9; //可以
    printf("%d",r);
    return 0;
}

总结

从几个例子其实也可一看出来,这三个关键字的作用,都是为了让可以确定的运算结果,在编译时就首页被执行完毕,这样,运行时等于只是操作一个具体的常量,不会在执行多余的运算,也就提高了一点运行速度。也就是说,被这三个关键字修饰的变量或者函数,即使不使用编译器、程序不运行,也能准确的知道他最终的值.这时候才能使用上述三个关键字功能

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1106106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python使用openpyxl读取excel图片

使用openpyxl读取excel中图片&#xff0c;并保存到本地. 需要的包。 from openpyxl import load_workbook from PIL import Image import cv2 import numpy as np具体实现 先把openpyxl读取的图片转换为Image对象&#xff0c;再将Image对象转换为numpy array&#xff0c;num…

【无标题】Docker入门到拿捏,图文码并茂

0. 项目部署的问题 大型项目组件较多,运行环境也较为复杂&#xff0c;部署时会碰到- -些问题: 依赖关系复杂&#xff0c;容易出现兼容性问题开发、测试、生产环境有差异 1. 认识Docker Docker如何解决依赖的兼容问题的? 将应用的Libs (函数库)、Deps (依赖)、配置与应用一…

V8引擎编译原理(VIP课程)

什么是V8 V8是谷歌的开源高性能JavaScript和WebAssembly引擎&#xff0c;用C编写。它被用于Chrome和Node.js等。它实现ECMAScript和WebAssembly&#xff0c;并在Windows 7或更高版本、macOS 10.12以及使用x64、IA-32、ARM或MIPS处理器的Linux系统上运行。V8可以独立运行&#…

KMP substring search 算法 案例分析

一、理解KMP算法如何运用后缀和前缀的信息 文本串text:abcxabcdabxabcdabcdabcy模式串pattern:abcdabcy 当发现不匹配的点&#xff0c;我们的目标不是在这个串中进行回溯操作。因此我们要检查的是 d 的前面的子串&#xff08;abc&#xff09;&#xff0c;在这个子串&#xff08…

【Qt-19】按Q退出应用程序

如何将Qt窗口应用程序改成控制台程序呢&#xff1f; 下面进入正文&#xff0c;如何控制控制台程序退出呢&#xff1f; 这里采用线程方式&#xff0c;通过单独线程监视用户输入来执行是否退出程序。 监视线程头文件thread.h #include <QThread> #include "TDRServe…

c++_learning-基础部分

文章目录 基础认识&#xff1a;语言特性&#xff08;面向对象编程&#xff09;&#xff1a;c的类&#xff08;相当于c中的结构体&#xff09;&#xff1a;三大特性&#xff1a;c包含四种编程范式&#xff1a;优缺点&#xff1a; c程序编译的过程&#xff1a;预处理->编译&am…

matlab中绘制 维诺图(Voronoi Diagram)

1.专业术语&#xff08;相关概念&#xff09;&#xff1a; 基点Site&#xff1a;具有一些几何意义的点 细胞Cell&#xff1a;这个Cell中的任何一个点到Cell中基点中的距离都是最近的&#xff0c;离其他Site比离内部Site的距离都要远。 Cell的划分&#xff1a;基点Site与其它的…

气膜式仓库:灵活创新,助力企业储存与物流升级

气膜式大空间仓库的建设不受地面条件限制&#xff0c;为企业提供了极大的便利。合理的仓储系统不仅是企业和厂商提高货品流动速度、确保生产、储运、配送顺利进行的关键&#xff0c;也是现代物流发展的需要。传统建筑在使用中存在一些不足&#xff0c;因此&#xff0c;我们需要…

科技新宠!拓世AI智能直播一体机揭秘,颠覆教学模式!

数字时代的铺展下&#xff0c;短视频和直播电商行业呈现出爆发式的增长&#xff0c;这种趋势正在日益融入人们的日常生活中&#xff0c;让短视频带货和直播带货逐渐成为一种独具中国特色的现象。与此同时&#xff0c;市场对专业人才的渴求也日渐加剧。国家以及相关地方政府纷纷…

Generative AI 新世界 | 大模型参数高效微调和量化原理概述

在上期文章&#xff0c;我们对比了在 Amazon SageMaker 上部署大模型的两种不同的部署方式。本期文章&#xff0c;我们将探讨两个目前大语言模型领域的开发者们都关注的两个热门话题&#xff1a;大型语言模型&#xff08;LLM&#xff09;的高效微调和量化。 微调大型语言模型允…

微信小程序调起微信支付

微信支付开发文档&#xff1a;wx.requestPayment(Object object) | 微信开放文档 一、先有一个提交订单页面 &#xff08;1&#xff09;wxml <view class"btn" bindtap"addOrder">{{btnText}}</view> 二、接入支付流程 &#xff08;1&…

element-ui 图片压缩上传

picture.js export const compressImgNew (file) > {return new Promise(resolve > {const reader new FileReader()const image new Image()image.onload (imageEvent) > {const canvas document.createElement(canvas) // 创建画布const context canvas.getCo…

工控机连接Profinet转Modbus RTU网关与水泵变频器Modbus通讯配置案例

Profinet转Modbus RTU网关是一个具有高性能的通信设备&#xff0c;它能够将工控机上的Profinet协议转换成水泵变频器可识别的Modbus RTU协议&#xff0c;实现二者之间的通信。通过这种方式&#xff0c;工控机可以直接控制水泵变频器的运行状态&#xff0c;改变其工作频率&#…

获取钉钉机器人的token及secret

一、下载安装 app不能自定义机器人&#xff0c;要客户端才行 二、进入组织/团队 三、创建群聊 1、发起群聊 2、创建内存群 群聊是内部的才行&#xff0c;只有内部的才支持自定义机器人 3、选中联系人 4、进入群设置 四、创建自定义机器人 1&#xff09; 进入机器人页面 2&…

工程云平台源码 建筑工地劳务实名制、危大工程监管平台源码

智慧工地的核心是数字化&#xff0c;它通过传感器、监控设备、智能终端等技术手段&#xff0c;实现对工地各个环节的实时数据采集和传输&#xff0c;如环境温度、湿度、噪音等数据信息&#xff0c;将数据汇集到云端进行处理和分析&#xff0c;生成各种报表、图表和预警信息&…

TSINGSEE风电场可视化智能视频集控监管系统,助力风电场无人值守监管新模式

一、方案背景 风能作为一种清洁的可再生能源&#xff0c;对于我国实现“双碳”目标尤为重要。风电场一般地处偏远地区&#xff0c;占地广、面积大&#xff0c;并且风机分布区域广泛、现场运行设备巡视难度大、及时性差。原有的监管系统智能化水平低&#xff0c;满足不了日常的…

腾讯待办关停什么意思?可替代的待办提醒软件来了

对于国内的成年人来说&#xff0c;几乎每个人都有至少一个微信账号要和亲朋好友、同事联系&#xff0c;而如果想要记录一些待办事项并准时接收提醒的话&#xff0c;可以直接在微信中使用“腾讯待办”这个小程序来记录待办事项并设置提醒时间。 不过值得注意的是&#xff0c;腾…

word中图片怎么批量缩小?超级简单好用!

word中图片批量缩小有两种角度进行操作&#xff0c;一种是通过批量裁剪图片进行缩小&#xff0c;一种是通过批量压缩图片进行缩小&#xff0c;下面根据这两种不同的角度介绍三种实用的方法&#xff0c;一起来看看吧&#xff5e; 方法一&#xff1a;通过批量裁剪图片缩小 1、点…

如何在脱敏数据中使用BERT等预训练模型

前几天有朋友问了一下【小布助手短文本语义匹配竞赛】的问题&#xff0c;主要是两个&#xff1b; 如何在脱敏数据中使用BERT&#xff1b;基于此语料如何使用NSP任务&#xff1b; 比赛我没咋做&#xff0c;因为我感觉即使认真做也打不过前排大佬[囧]&#xff0c;太菜了&#x…

RK3288 Android11 RTL8723DS WiFi 和 蓝牙Bluetooth 适配

目录 一、RTL8723DS WiFi 适配 --- 篇章1、原理图分析&#xff08;WiFi部分&#xff09;补充:RTL8723DS时钟输入源讲解 2、根据原理图修改设备树和编辑驱动文件3、实验验证4、RTL8723DS WIFI驱动参考文档和博客网站 二、RTL8723DS 蓝牙Bluetooth 适配 --- 篇章1、原理图分析&am…