C++中const与constexpr的区别
在C++中,`const`和`constexpr`都用于定义常量,但它们的用途和行为有显著区别:
### 1. **初始化时机**
- **`const`**:表示变量是只读的,但其值可以在**编译时或运行时**初始化。
```cpp
const int a = 5; // 编译时初始化
const int b = some_function(); // 运行时初始化(合法)
```
- **`constexpr`**:变量必须在**编译时**初始化,且初始化表达式必须是常量。
```cpp
constexpr int c = 5; // 合法
constexpr int d = some_function(); // 仅当 some_function() 是 constexpr 函数时合法
```
---
### 2. **应用场景**
- **`const`**:用于声明运行时常量,确保值不可修改。
```cpp
int x = 10;
const int y = x; // 合法,但 y 的值在运行时确定
```
- **`constexpr`**:用于需要编译时常量的场景(如数组大小、模板参数)。
```cpp
constexpr int size = 10;
int arr[size]; // 合法,size 是编译时常量
int x = 10;
constexpr int invalid_size = x; // 错误:x 不是常量表达式
```
---
### 3. **函数与对象**
- **`constexpr` 函数**:可以在编译时求值(若参数是常量)。
```cpp
constexpr int square(int x) { return x * x; }
constexpr int val = square(5); // 编译时计算(val = 25)
int y = square(10); // 运行时计算
```
- **`const` 成员函数**:表示函数不会修改对象状态,但调用时机不限定于编译时。
```cpp
class MyClass {
public:
int getValue() const { return value; } // 运行时调用
private:
int value;
};
```
- **`constexpr` 对象**:允许在编译时构造对象。
```cpp
class Point {
public:
constexpr Point(int x, int y) : x(x), y(y) {}
constexpr int getX() const { return x; }
private:
int x, y;
};
constexpr Point p(3, 4); // 编译时构造
constexpr int x = p.getX(); // x = 3(编译时获取值)
```
---
### 4. **指针与引用**
- **`const` 指针**:指针本身或指向的值不可修改。
```cpp
const int* ptr1 = &a; // 指向的值不可变
int* const ptr2 = &b; // 指针本身不可变
```
- **`constexpr` 指针**:必须指向编译时确定的地址(如全局变量或静态变量)。
```cpp
constexpr int* ptr3 = nullptr; // 合法
int global = 42;
constexpr int* ptr4 = &global; // 合法(全局变量地址在编译时确定)
```
---
### 总结
| **特性** | `const` | `constexpr` |
|------------------------|----------------------------------|---------------------------------|
| **初始化时机** | 编译时或运行时 | 必须编译时 |
| **用途** | 运行时常量 | 编译时常量、模板元编程 |
| **函数修饰** | 表示函数不修改对象状态 | 函数可在编译时求值 |
| **对象构造** | 运行时构造 | 允许编译时构造(需 constexpr 构造函数) |
| **指针/引用** | 可指向动态内存 | 必须指向编译时确定的地址 |
- **优先使用 `constexpr`**:当需要编译时常量或优化性能时(如数组大小、模板参数)。
- **使用 `const`**:当仅需运行时常量(如函数参数、返回值保护)。
在编程中,「编译时」和「运行时」是两个关键阶段,它们的区别直接影响了代码的行为和结果。以下是它们的核心区别:
---
### **1. 时间与操作**
- **编译时 (Compile Time)**
- **时间点**:代码被编译器处理(生成可执行文件前)。
- **操作内容**:
- 语法检查(如括号是否匹配、变量是否声明)。
- 类型检查(如 `int x = "hello"` 会报错)。
- 优化(如删除未使用的变量、内联函数)。
- 生成机器码或中间代码。
- **示例**:
```cpp
int x = 5;
std::string s = x; // 编译错误:类型不匹配
```
- **运行时 (Runtime)**
- **时间点**:程序实际执行时(用户运行可执行文件后)。
- **操作内容**:
- 内存分配(如 `new` 和 `malloc`)。
- 动态逻辑(如用户输入、文件读写)。
- 异常处理(如除以零、空指针访问)。
- **示例**:
```cpp
int x = 0;
std::cin >> x; // 运行时输入
int y = 10 / x; // 运行时可能崩溃(如果 x=0)
```
---
### **2. 输入依赖**
- **编译时**:
- 所有数据必须是已知的、固定的(如常量表达式)。
- 示例:数组大小、模板参数、`constexpr` 值。
```cpp
constexpr int size = 10;
int arr[size]; // 合法:size 是编译时常量
```
- **运行时**:
- 数据可以是动态的(如用户输入、随机数)。
```cpp
int size;
std::cin >> size; // 运行时输入
int* arr = new int[size]; // 动态内存分配(运行时确定大小)
```
---
### **3. 错误类型**
- **编译时错误**:
- 由编译器发现(如语法错误、类型不匹配)。
- 必须修复后才能生成可执行文件。
```cpp
int x = "hello"; // 编译错误:类型不匹配
```
- **运行时错误**:
- 程序执行时发生的错误(如内存泄漏、空指针访问)。
- 可能通过测试或异常处理捕获。
```cpp
int* ptr = nullptr;
*ptr = 5; // 运行时崩溃(空指针解引用)
```
---
### **4. 性能影响**
- **编译时计算**:
- 由编译器完成(如 `constexpr` 函数),减少运行时开销。
```cpp
constexpr int factorial(int n) { return (n <= 1) ? 1 : n * factorial(n-1); }
constexpr int result = factorial(5); // 编译时计算(result = 120)
```
- **运行时计算**:
- 在程序执行时完成,可能占用 CPU 和内存资源。
```cpp
int x = 5;
int result = 1;
for (int i = 1; i <= x; i++) { result *= i; } // 运行时计算
```
---
### **5. 实际应用场景**
- **编译时需要确定的场景**:
- 数组大小、模板参数、`static_assert` 断言。
```cpp
template <int N>
struct Array { int data[N]; }; // N 必须是编译时常量
```
- **运行时需要处理的场景**:
- 用户交互(输入/输出)、网络请求、动态内存分配。
```cpp
std::string name;
std::cout << "Enter your name: ";
std::cin >> name; // 运行时输入
```
---
### **总结**
| **特性** | **编译时** | **运行时** |
|------------------|-------------------------------------|-------------------------------------|
| **时间点** | 代码编译阶段 | 程序执行阶段 |
| **输入依赖** | 必须已知(常量) | 可以是动态的(变量或用户输入) |
| **错误类型** | 语法错误、类型错误 | 崩溃、内存泄漏、逻辑错误 |
| **性能优化** | 通过编译时计算减少运行时开销 | 依赖算法和硬件性能 |
| **典型操作** | 静态类型检查、模板实例化 | 内存分配、异常处理、I/O 操作 |
---
### **为什么程序员需要关注两者的区别?**
1. **优化性能**:将能提前计算的任务放在编译时(如 `constexpr`)。
2. **避免错误**:通过编译时检查(如类型安全)减少运行时崩溃风险。
3. **灵活设计**:区分静态(编译时)和动态(运行时)逻辑,提高代码可维护性。
相关文章:
C++中const与constexpr的区别
在C中,const和constexpr都用于定义常量,但它们的用途和行为有显著区别: ### 1. **初始化时机** - **const**:表示变量是只读的,但其值可以在**编译时或运行时**初始化。 cpp const int a 5; // 编译…...
解决Windows安全中心显示空白页面
1、电脑重装系统后,发现原本一些软件打不开了,电脑莫名认为有病毒,自动删除插件。附图。 2、第一反应是电脑防火墙的原因,默认威胁防护识别到了病毒软件,自动删除。在开始屏幕搜Windows安全中心,打开之后发…...
三国战纪119通关笔记
文章目录 诸葛一币通关孙姬马王夏侯渊孟优夏侯惇张辽貂蝉吕蒙沙摩柯破阵及吕布陆逊左慈(跳)许褚黄盖彻里吉(跳)魏延(跳)司马懿曹操道具的安排道具-天师符(废弃)道具-九节杖道具-援军令(废弃)道具-土雷(废弃) 笔者是个菜鸡,什么天王难度无伤,天王难度5禁什…...
Android audio系统五 AudioPolicy 策略配置详解
引用:Android 音频策略配置文件解析流程 audio_policy_configuration.xml 是 Android 音频系统的核心配置文件,它定义了音频硬件接口、设备路由和基本策略。下面我将详细介绍这个文件的结构、关键配置项和实际应用。audio_policy_configuration.xml 是 …...
【MQ篇】初识MQ!
目录 一、什么是MQ?简单来说就是个“快递中转站” 📦二、为什么要用MQ?用了它,好处多多!🤩三、MQ的应用场景:各行各业都能用!🌍四、MQ的优缺点:硬币的两面&am…...
2、SpringAI接入ChatGPT与微服务整合
2、SpringAI接入ChatGPT与微服务整合 小薛博客AI 大模型资料 1、SpringAI简介 https://spring.io/projects/spring-ai Spring AI是一个人工智能工程的应用框架。其目标是将Spring生态系统的设计原则(如可移植性和模块化设计)应用于人工智能领域&#…...
【Linux】多进程任务模块
创建多个进程,同时完成任务 task.c #include <sys/types.h> #include <unistd.h> #include<stdio.h> #include <sys/wait.h> int create_process_tasks(Task_fun_t tasks[],int tsak_cnt) {pid_t pid;int i 0;for(i 0;i < 4;i){pid …...
榕壹云预约咨询系统:基于ThinkPHP+MySQL+UniApp打造的灵活预约小程序解决方案
数字化咨询场景的痛点与解决方案 在心理咨询、医疗问诊、法律咨询等需要预约服务的场景中,传统线下预约存在效率低、管理复杂、资源分配不均等问题。榕壹云预约咨询系统基于ThinkPHPMySQLUniApp技术栈开发,为咨询类行业提供了一套高效、安全、可扩展的数…...
鸿蒙NEXT开发LRUCache缓存工具类(单例模式)(ArkTs)
import { util } from kit.ArkTS;/*** LRUCache缓存工具类(单例模式)* author 鸿蒙布道师* since 2025/04/21*/ export class LRUCacheUtil {private static instance: LRUCacheUtil;private lruCache: util.LRUCache<string, any>;/*** 私有构造函…...
opencv 图像矫正的原理
图像矫正的原理是透视变换,下面来介绍一下透视变换的概念。 听名字有点熟,我们在图像旋转里接触过仿射变换,知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换,…...
计算机前沿技术课程论文 K-means算法在图像处理的应用
K-means算法在图像处理的应用 这是本人在计算机前沿技术课程中的课程论文文章,为了方便大家参考学习,我把完整的论文word文档发到了我的资源里,有需要的可以自取。 点击完整资源链接 目录 K-means算法在图像处理的应用摘要:引言1…...
【股票数据API接口37】如何获取股票指数实时数据之Python、Java等多种主流语言实例代码演示通过股票数据接口获取数据
如今,量化分析在股市领域风靡一时,其核心要素在于数据,获取股票数据,是踏上量化分析之路的第一步。你可以选择亲手编写爬虫来抓取,但更便捷的方式,莫过于利用专业的股票数据API接口。自编爬虫虽零成本&a…...
【仓颉 + 鸿蒙 + AI Agent】CangjieMagic框架(17):PlanReactExecutor
CangjieMagic框架:使用华为仓颉编程语言编写,专门用于开发AI Agent,支持鸿蒙、Windows、macOS、Linux等系统。 这篇文章剖析一下 CangjieMagic 框架中的 PlanReactExecutor。 1 PlanReactExecutor的工作原理 #mermaid-svg-OqJUCSoxZkzylbDY…...
docker harbor私有仓库登录报错
docker harbor私有仓库登录报错如下: [rootsrv-1 ~]# docker login -u user1 -p pwd1 harbor.chinacloudapi.cn WARNING! Using --password via the CLI is insecure. Use --password-stdin. Error response from daemon: Get "https://harbor.chinacloudapi.…...
IQ信号和实信号的关系与转换的matlab实现
IQ信号 IQ信号通常是指两路正交的信号(I路和Q路),在实际信号采样中,通常会进行IQ采样,将实信号转换为复基带信号进行存储。 IQ信号转实信号 IQ信号转为实信号,其实就是将IQ两路正交信号通过上变频合并为一个实数的带通信号,这通常在通信系统中用于将基带信号调制到载…...
WSL2-Ubuntu22.04安装URSim5.21.3
WSL2-Ubuntu22.04安装URSim5.21.3 准备安装启动 准备 名称版本WSL2Ubuntu22.04URSim5.21.3VcXsrvNaN WSL2安装与可视化请见这篇:WSL2-Ubuntu22.04-配置。 安装 我们是wsl2-ubuntu22.04,所以安装Linux版本的URSim,下载之前需要注册一下,即…...
blender 录课键位显示插件(图文傻瓜式安装)
1、下载 点击这个链接进行下载https://github.com/nutti/Screencast-Keys 下载好不用解压 2、安装 打开blender进行安装 点击编辑选择偏好设置 选择插件再点击这个下箭头 选择从磁盘安装 然后找到自己刚刚下载好的,点击从磁盘安装 安装完成后勾选上插件 …...
天翼云手机断开连接2小时关机
2025-04-21 天翼云手机断开连接2小时自动 天翼云手机 4元1个月 天翼云手机永不关机 天翼云手机不休眠 天翼云手机断开连接时,界面显示:离线运行,2小时后自动关机 电脑每小时自动连接一次 手机每小时自动连接一次...
基于 FFmpeg 的音视频处理基础原理与实验探究
目录 1 基本知识1.1 解封装1.2 AAC和ADTS说明 1.3 H2641.3.1 H264编码结构解析1.3.2 NALU1.3.2 分类 2 实验1 探究音视频信息2.1 重要结构体介绍2.2 相关的API 3 实验二 提取AAC数据4 实验三 提取h264 1 基本知识 1.1 解封装 封装的逆向操作:封装是把音频流、视频流…...
【Rust 精进之路之第5篇-数据基石·下】复合类型:元组 (Tuple) 与数组 (Array) 的定长世界
系列: Rust 精进之路:构建可靠、高效软件的底层逻辑 作者: 码觉客 发布日期: 2025-04-20 引言:从原子到分子——组合的力量 在上一篇【数据基石上】中,我们仔细研究了 Rust 的四种基本标量类型࿱…...
【前端样式】用 aspect-ratio 实现等比容器:视频封面与图片占位的终极解决方案
在网页开发中,处理视频封面、图片卡片等需要固定比例的容器一直是前端工程师的必修课。本文将以 aspect-ratio 属性为核心,深入探讨如何优雅实现等比容器,并通过完整代码示例和常见问题解析,助你彻底掌握这一现代布局利器。 目录…...
【网络安全】OWASP 十大漏洞
1. OWASP 十大漏洞 为了应对未来的风险,安全专业人员需要随时掌握最新信息。之前,您了解了CVE 列表,这是一个公开的已知漏洞和暴露列表。CVE 列表是全球安全社区相互共享信息的重要信息来源。 在本文中,您将了解安全专业人士参考…...
我用deepseek做了一个提取压缩文件夹下pdf和word文件工具
由于最近需要把大量的压缩文件的pdf和word文件统一复制到一个文件夹中。 我们一般正常操作方式的是把一个压缩文件一个一个解压,然后在把一个的解压好的文件夹下文件复制到另外一个文件夹中。 这个也需太繁琐了,从以往统计的需要花费两个小时间&#x…...
【Docker】在容器中使用 NVIDIA GPU
解决容器 GPU 设备映射问题,实现 AI 应用加速 🔗 官方文档:NVIDIA Container Toolkit GitHub 常见错误排查 若在运行测试容器时遇到以下错误: docker: Error response from daemon: could not select device driver ""…...
机器人进阶---视觉算法(五)仿射变换和投影变换有什么区别
仿射变换和投影变换有什么区别 1. 定义2. 几何特性3. 变换矩阵4. 应用场景5. Python代码示例仿射变换投影变换6. 总结仿射变换和投影变换都是图像处理中常用的几何变换方法,但它们在变换性质、应用场景和变换矩阵等方面存在一些关键区别。 1. 定义 仿射变换 (Affine Transform…...
如何在 Amazon EC2 上部署 Java(Spring Boot 版)
让我们学习如何将 Java Spring Boot Web 服务器部署到 Amazon EC2。每月只需 3 美元。 使用 Azure,您可能不知道要花费多少钱。 Spring Boot 项目示例 在本教程中,我们将重点介绍如何将 Java Spring Boot 服务器部署到 Amazon EC2,因此我们不…...
IDEA打不开、打开报错
目录 场景异常原因解决 场景 1、本机已经安装了IDEA 2、再次安装另外一个版本的IDEA后打不开、打开报错 异常 这里忘记截图了。。。 原因 情况1-打不开:在同一台电脑安装多个IDEA是需要对idea的配置文件进行调整的,否则打不开 情况2-打开报错&#…...
【React】项目的搭建
create-react-app 搭建vite 搭建相关下载 在Vue中搭建项目的步骤:1.首先安装脚手架的环境,2.通过脚手架的指令创建项目 在React中有两种方式去搭建项目:1.和Vue一样,先安装脚手架然后通过脚手架指令搭建;2.npx create-…...
如何提高单元测试的覆盖率
一、定位未覆盖的代码 利用 IDEA 的覆盖率工具: 右键测试类 → Run with Coverage,或使用 AltShiftF10(Windows)打开运行菜单选择覆盖率。查看高亮标记: 绿色:已覆盖代码行。红色&#x…...
【SAP ME 43】RESRCE表操作导致HANA中表锁定解决方案
症状 SAP ME 通过执行以下 SQL 查询导致 RESRCE 表上的 HANA 数据库锁: 从 RESRCE WHERE HANDLE =? 选择站点待更新 或者 SELECT HANDLE FROM RESRCE WHERE HANDLE =... 用于更新 其他条款 HANA、锁、RESRCE 原因和前提条件 该问题是由运行 SQL FOR UPDATE 查询时的 …...
