constexpt

constexpt

constexpt是C++11引入的新的关键字,它用于在编译时而非运行时计算函数或变量的值。这个特性对于提高程序效率和优化代非常有用。

编译时常量和运行时常量

编译时常量(Compile-time Constants)和运行时常量(Runtime Constants)是指常量在程序执行过程中被确定的时间点不同。

  • 编译时常量

编译时常量是指其值在程序编译阶段就已经确定并嵌入到代码中的常量。

它们通常是直接赋值的,或者通过在编译时可解析的表达式计算得到。

特点

  • 由于它们的值在编译时就已确定,因此运行时无需再计算,这可以提升程序运行效率。

  • 编译时常量通常直接存储在程序的只读数据段,减少了运行时内存的使用。

使用场景

  • 定义数组大小、初始化类的静态成员、以及在程序中使用的任何固定值。
  • 在模板元编程中广泛使用,用于在编译时进行复杂的计算。

实现方式

  • 在 C++ 中,使用 constexpr 关键字来定义编译时常量。

  • 运行时常量

定义

  • 运行时常量是指其值在程序运行时才确定的常量。
  • 它们的值可能依赖于运行时的输入或其他只有在程序执行时才可知的数据。

特点

  • 灵活性:提供了根据运行时情况动态确定值的能力。
  • 性能开销:由于需要在程序运行时计算,可能会引入额外的性能开销。

使用场景

  • 当常量值依赖于用户输入、文件读取、或其他运行时环境因素时。
  • 在需要根据不同的运行时条件选择不同常量值的情况下使用。

实现方式

  • 通常通过 const 关键字定义,但其值赋予操作发生在程序运行时。

  • 对比

确定时间:

  • 编译时常量:在编译阶段确定。
  • 运行时常量:在运行阶段确定。

优化:

  • 编译时常量:有助于性能优化,因为消除了运行时计算的需要。
  • 运行时常量:提供灵活性,但可能增加性能开销。

使用关键字:

  • 编译时常量:C++ 中使用 constexpr
  • 运行时常量:常用 const,但赋值发生在运行时。

特点

编译时计算

constexpr 用于创建在编译时就能被计算的表达式。这包括变量、函数和对象构造函数。

constexpr 用于变量时,它表明该变量的值是一个编译时常量。这意味着变量的值必须在编译时就已知,并且在程序的整个生命周期中保持不变。

constexpr int max_size = 100; // 编译时常量

constexpr 用于函数时,它表示该函数在其所有参数都是常量表达式时,可以在编译时执行。这意味着函数的返回值也必须是编译时常量。

constexpr int factorial(int n) {return n <= 1 ? 1 : n * factorial(n - 1);
}constexpr int fact_5 = factorial(5); // 编译时计算 5 的阶乘

这里,factorial 函数被定义为 constexpr,这意味着它可以在编译时计算阶乘。因此,fact_5 的值(120)将在编译时被计算并嵌入到编译后的代码中。

在 C++11 之后,constexpr 还可以用于对象的构造函数。这允许在编译时创建和初始化对象。

class Point {
public:constexpr Point(double xVal, double yVal) : x(xVal), y(yVal) {}constexpr double getX() const { return x; }constexpr double getY() const { return y; }private:double x, y;
};constexpr Point origin(0.0, 0.0); // 编译时创建 Point 对象

在这个例子中,Point 类的构造函数被标记为 constexpr,这使得我们可以在编译时创建和初始化 Point 对象。

注意:constexpr 函数或构造函数在编译时计算时必须满足一些条件,比如不能有未定义的行为、不能有非常量表达式的分支等。如果 constexpr 表达式在编译时不能求值,它将导致编译错误。

函数限制

C++11 中的 constexpr 函数限制

在 C++11 中,constexpr 函数的使用受到相对严格的限制:

  1. 单一返回语句:函数体内只能包含一个 return 语句。
  2. 无循环和分支结构:不允许使用循环(如 forwhile)和复杂的分支结构(如 if-else)。
  3. 简单的逻辑:函数通常只能执行简单的计算,如基本的算术运算。、

如:

constexpr int add(int a, int b) {return a + b; // 只有一个 return 语句
}
C++14 中的 constexpr 函数限制放宽

C++14 放宽了这些限制,使 constexpr 函数变得更加强大和灵活:

  1. 多个返回语句:允许函数体内有多个 return 语句。
  2. 支持循环和分支:可以使用循环和条件判断等复杂结构。
  3. 更复杂的逻辑:函数可以执行更复杂的逻辑和计算。

如:

constexpr int factorial(int n) {if (n <= 1) {return 1;} else {return n * factorial(n - 1); // 使用了递归}
}

类型限制

constexpr 的类型限制是 C++ 标准中的一个重要部分,确保了在编译时可以安全且可靠地计算 constexpr 表达式。这些类型限制主要关注于字面类型(Literal Type),这是一类特定的类型,适用于编译时的计算。以下是关于字面类型和 constexpr 的详细解释:

字面类型(Literal Type)

字面类型是一类特定的数据类型,它们适用于 constexpr 表达式。字面类型包括:

  1. 算术类型:包括所有的整数类型(如 intlong)和浮点类型(如 floatdouble)。

  2. 指针类型:任何类型的指针(包括指向函数的指针)。

  3. 引用类型:任何类型的引用。

  4. 某些类类型

    • 类类型必须满足特定条件才能被视为字面类型。这些条件包括但不限于:
      • 所有成员都必须是字面类型。
      • 必须有一个 constexpr 构造函数。
      • 如果有析构函数,它必须是平凡的(trivial)。

这些类型限制确保了 constexpr 表达式在编译时是确定的和安全的。它们可以在编译时完全计算,没有未定义的行为或依赖于运行时才能确定的信息。

constexpr 变量和函数的类型限制

当定义 constexpr 变量或函数时,必须确保它们的类型是字面类型:

  • 变量constexpr 变量必须是字面类型。例如,constexpr int max_size = 100; 中的 int 是字面类型。

  • 函数constexpr 函数的返回类型和所有参数类型必须是字面类型。例如,constexpr int add(int a, int b) { return a + b; } 中的返回类型 int 和参数类型 int 都是字面类型。

类类型的 constexpr 示例
class Point {
public:constexpr Point(double xVal, double yVal) : x(xVal), y(yVal) {}constexpr double getX() const { return x; }constexpr double getY() const { return y; }private:double x, y; // double 是字面类型
};constexpr Point origin(0.0, 0.0); // Point 类是字面类型

在这个例子中,Point 类是一个字面类型,因为它的所有成员都是字面类型,并且它有一个 constexpr 构造函数。

constexpt与const

const 变量的值可以在编译时或运行时被设定。这意味着它们可以根据运行时的计算或输入来确定其值。

const int max_users = 100; // 编译时常量
const int current_users = getUsersCount(); // 运行时常量

用途和好处

  1. 性能提升
    • 由于在编译时完成计算,constexpr 可以显著减少程序运行时的时间和资源消耗。
  2. 内存使用优化
    • 编译时计算的结果通常存储在程序的只读数据段,降低了运行时的内存需求。
  3. 代码可读性和可维护性提高
    • constexpr 提供了一种明确和直接的方式来表示编译时常量,使得代码意图更清晰。
    • 减少了运行时错误的可能性,因为很多计算在编译时就已确定。
  4. 更安全的代码
    • 编译时计算减少了运行时可能的错误和异常,提高了代码的整体安全性。

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

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

相关文章

8年经验之谈 —— 如何使用自动化工具编写测试用例?

以下为作者观点&#xff0c;仅供参考&#xff1a; 在快速变化的软件开发领域&#xff0c;保证应用程序的可靠性和质量至关重要。随着应用程序复杂性和规模的不断增加&#xff0c;仅手动测试无法满足行业需求。 这就是测试自动化发挥作用的地方&#xff0c;它使软件测试人员能…

leetcode做题笔记1410. HTML 实体解析器

「HTML 实体解析器」 是一种特殊的解析器&#xff0c;它将 HTML 代码作为输入&#xff0c;并用字符本身替换掉所有这些特殊的字符实体。 HTML 里这些特殊字符和它们对应的字符实体包括&#xff1a; 双引号&#xff1a;字符实体为 &quot; &#xff0c;对应的字符是 "…

python appium 官网下载

找了半天吐了 https://github.com/appium/appium-desktop/releases/tag/v1.22.3-4

Hibernate批量处理数据

概念&#xff1a; 批量处理数据是指在一个事务场景中处理大量数据。 在应用程序中难以避免进行批量操作&#xff0c;Hibernate提供了以下方式进行批量处理数据&#xff1a; (1)使用HQL进行批量操作 数据库层面 executeUpdate() (2)使用JDBC API进行批量操作 数据库层面 …

Vue学习笔记-Object.defineproperty函数

文章目录 前文提要Object.defineProperty作用Object.defineProperty参数使用例图getter&#xff0c;也就是get函数setter&#xff0c;也就是set函数 前文提要 本人仅做个人学习记录&#xff0c;如有错误&#xff0c;请多包涵 Object.defineProperty作用 当在js中声明了一个变…

王道p150 20.将给定的表达式树转化为等价的中缀表达式(通过括号反应操作符的计算次序)

本题代码如下 void btreetoexp(tree t, char deep) {if (t NULL)return;else if (t->lchild NULL && t->rchild NULL)printf("%c", t->data);//输出操作数&#xff0c;不加括号else {if (deep > 1)printf("(");btreetoexp(t->l…

Rust语言入门教程(二) - 变量与作用域

变量与作用域 变量的声明与初始化 Rust的基本语法格式如下&#xff1a; fn main(){let bunnies 2; }语句以分号结尾&#xff0c;用花括号包含语句块。 Rust的语法其实借鉴了很多其他的语言&#xff0c;比如C语言和Python&#xff0c; 所以变量定义的格式看起来也跟很多我们…

shell 脚本的函数和数组

函数 —— 封装的一个公式&#xff1a;sin、cos、tan —— 函数为脚本的别名 —— 函数就是一个功能模块&#xff0c;在函数中写执行的命令即可&#xff1b;使用函数可以避免代码重复&#xff0c;增加可读性&#xff0c;简化脚本&#xff0c;使用函数可以将大的工程分割为若…

Vue中动态class方法

1.方法一&#xff1a;只需要展示一个class样式&#xff0c;但是动态取值 <div :class"aaa"></div>data:{return () {aaa:colorRed} }.colorRed {color: red; } 2.方法二&#xff1a;表达式判断是否展示class里面的样式 <div :class"{colorRed…

函数与数组

一.函数 1、函数的作用 定义较为复杂的但是需要重复使用的内容&#xff0c;以便再次使用&#xff0c;可以直接调用&#xff0c;节约时间&#xff0c;提高效率。 语句块定义成函数约等于别名&#xff0c;定义函数&#xff0c;再引用函数。 封装的可重复利用的具有特定功能的…

python+django高校科研项目管理系统2u3mx

高校科研项目管理系统采用拟开发的高校科研项目管理系统通过测试,确保在最大负载的情况下稳定运转,各个模块工作正常,具有较高的可用性。系统整体界面简洁美观,用户使用简单,满足用户需要。在因特网发展迅猛的当今社会,高校科研项目管理系统必然会成为在数字信息化建设的一个重…

Linux 查看 CPU 信息相关命令

目录 lscpu top htop lscpu lscpu 命令是用于显示有关 CPU 架构的信息&#xff0c;而不是用于实时监视 CPU 负载。它提供有关 CPU 类型、核心数、线程数、架构等的详细信息。 lscpu top 命令会显示系统的实时状态&#xff0c;包括 CPU 使用率、内存使用率等。按下键盘上的…

一文详解Vue生命周期

Vue是一种流行的用于构建用户界面的渐进式JavaScript框架。Vue框架在开发过程中&#xff0c;特别强调对生命周期的理解和管理。通过使用生命周期钩子函数&#xff0c;开发者能够精确地控制Vue实例的创建、挂载、更新以及销毁过程。本文将对Vue的生命周期进行详细的介绍&#xf…

YOLOv8训练自己的目标检测数据集

YOLOv8训练自己的目标检测数据集 目录标题 源码下载环境配置安装包训练自己的数据集数据集文件格式数据集文件配置超参数文件配置训练数据集命令行训练脚本.py文件训练 进行detect显示detect的效果 源码下载 YOLOv8官方的GitHub代码&#xff0c;同时上面也有基础环境的配置要…

IntelliJ IDEA 16创建Web项目

首先要理解一个概念&#xff1a;在IntelliJ IDEA中“new Project”相当于eclipse中的工作空间&#xff08;Workspace&#xff09;&#xff0c;而“new Module”相当于eclipse中的工程&#xff08;Project&#xff09;。以下均采用Intellij的说法&#xff0c;请自行对照转换理解…

Maven仓库清除remote.repositories、lastUpdated、sha1脚本

Maven仓库清除remote.repositories、lastUpdated、sha1脚本 1. 脚本功能 清除本地maven仓库的_remote.repositories、sha1、lastUpdated的文件 2. 脚本内容 set REPOSITORY_PATH%cd% rem 搜索中... for /f "delims" %%i in (dir /b /s "%REPOSITORY_PATH%\*…

Java 关键字:synchronized详解

synchronized详解 基本使用源码解析常见面试题好书推荐 基本使用 Java中的synchronized关键字用于在多线程环境下确保数据同步。它可以用来修饰方法和代码块 当一个线程访问一个对象的synchronized方法或代码块时&#xff0c;其他线程将无法访问该对象的其他synchronized方法或…

【愚公系列】2023年11月 Java教学课程 188-SpringCloud(Feign远程调用)

&#x1f3c6; 作者简介&#xff0c;愚公搬代码 &#x1f3c6;《头衔》&#xff1a;华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xf…

如何通过宝塔面板搭建一个本地MySQL数据库服务并实现远程访问

宝塔安装MySQL数据库&#xff0c;并内网穿透实现公网远程访问 文章目录 宝塔安装MySQL数据库&#xff0c;并内网穿透实现公网远程访问前言1.Mysql服务安装2.创建数据库3.安装cpolar3.2 创建HTTP隧道 4.远程连接5.固定TCP地址5.1 保留一个固定的公网TCP端口地址5.2 配置固定公网…

浙江师范黄昌勤老师关于情感分析的讲座

回放&#xff1a;https://share.weiyun.com/Wvaw4OoY 收获很大&#xff1a; 写几点&#xff0c; 1&#xff1a;小二聚焦 精细更有用 2&#xff1a;高产的秘诀就是 专注一个领域&#xff0c;不断延展。 3&#xff1a;好的文章技术不是本质&#xff0c;本质还是解决了什么教育问…