关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码
这哥三之间的关系是有趣的,不妨看看这个:
cv (const and volatile) type qualifiers - cppreference.com
mutable
permits modification of the class member declared mutable even if the containing object is declared const.
即便一个对象是const的,它内部的成员变量如果被mutable修饰,则此成员变量依旧可以被修改。
const
很常见,用途如其字面意义:别改变它"作用域"内的对象。
volatile
就如其含义:生性活泼,莫对其"作用域"下的对象指手画脚。这里着重说一下volatile。
volatile相关特性
1. 易变性。所谓的易变性,在汇编层面反映出来,就是两条语句,下一条语句不会直接使用上一条语句对应的volatile变量的寄存器内容,而是重新从内存中读取。
特性。
2. "不可优化"特性。volatile告诉编译器,不要对我这个变量进行各种激进的优化,甚至将变量直接消除,保证程序员写在代码中的指令,一定会被执行。
3. "顺序性",能够保证volatile变量间的顺序性,编译器不会进行乱序优化。 C/C++ Volatile变量,与非Volatile变量之间的操作,是可能被编译器交换顺序的。C/C++ Volatile变量间的操作,是不会被编译器交换顺序的。哪怕将所有的变量全部都声明为volatile,哪怕杜绝了编译器的乱序优化,但是针对生成的汇编代码,CPU有可能仍旧会乱序执行指令,导致程序依赖的逻辑出错,volatile对此无能为力 针对这个多线程的应用,真正正确的做法,是构建一个happens-before语义(请见下面的内存顺序说明)。
特别注意的误区
volatile和多线程这种并行数据同步机制无关,也不能解决这类问题。相关问题请见:
内存顺序 std::memory_order - cppreference.com
const 和 volatile 关键字可更改处理指针的方式。 const 关键字指定指针在初始化后无法修改;此后指针将受到保护,防止进行修改。
volatile 关键字指定与后跟的名称关联的值可由用户应用程序中的操作以外的操作修改。 因此,volatile 关键字对于声明共享内存中可由多个进程访问的对象或用于与中断服务例程通信的全局数据区域很有用。
如果某个名称被声明为 volatile,则每当程序访问该名称时,编译器都会重新加载内存中的值。 这将显著减少可能的优化。 但是,当对象的状态可能意外更改时,这是保证可预见的程序性能的唯一方法。
如果将 struct 成员标记为 volatile,则 volatile 将传播到整个结构。 如果结构不具有可通过使用一个指令在当前体系结构上复制的长度,则此结构上可能完全丢失 volatile。
volatile 关键字失效
如果满足下列条件之一,则 volatile 关键字可能对字段不起作用:
1. 可变字段的长度超过可使用一条指令在当前体系结构上复制的最大大小。
2. 最外层包含 struct 的长度 - 或如果它是可能嵌套的 struct 的成员 - 超过可使用一条指令在当前体系结构上复制的最大大小。
尽管处理器不会对不可缓存的内存访问重新排序,但必须将不可缓存的变量标记为 volatile,从而保证此编译器不会对内存访问重新排序。
声明为 volatile 的对象不在某些优化中使用,因为它们的值可以随时更改。 系统在请求易失对象时始终读取该对象的当前值,即使前面的指令要求从同一对象获取值也是如此。 此外,对象的值会立即在赋值时写入。
volatile 原理源码示例
注:以下所有示例的c++源码一致,只区分是否使用volatile关键字
c++源程序:
#include <stdio.h>
int main(int argc, char** argv)
{auto sk = argc;int a = 11 << sk;int b = 19 + argc;int rv = a + b * 8;rv *= sk;return rv;
}
VS Debug环境MASM反汇编
没有使用volatile关键字修饰
反汇编代码:
00007FF7DE032993 mov eax,dword ptr [argc]
00007FF7DE032999 mov dword ptr [sk],eax
00007FF7DE03299C mov eax,dword ptr [sk]
00007FF7DE03299F mov ecx,0Bh
00007FF7DE0329A4 mov dword ptr [rbp+134h],ecx
00007FF7DE0329AA movzx ecx,al
00007FF7DE0329AD mov eax,dword ptr [rbp+134h]
00007FF7DE0329B3 shl eax,cl
00007FF7DE0329B5 mov dword ptr [a],eax
00007FF7DE0329B8 mov eax,dword ptr [argc]
00007FF7DE0329BE add eax,13h
00007FF7DE0329C1 mov dword ptr [b],eax
00007FF7DE0329C4 mov eax,dword ptr [a]
00007FF7DE0329C7 mov ecx,dword ptr [b]
00007FF7DE0329CA lea eax,[rax+rcx*8]
00007FF7DE0329CD mov dword ptr [rv],eax
00007FF7DE0329D0 mov eax,dword ptr [rv]
00007FF7DE0329D3 imul eax,dword ptr [sk]
00007FF7DE0329D7 mov dword ptr [rv],eax
00007FF7DE0329DA mov eax,dword ptr [rv]
00007FF7DE0329DD lea rsp,[rbp+148h]
00007FF7DE0329E4 pop rdi
00007FF7DE0329E5 pop rbp
00007FF7DE0329E6 ret
使用volatile关键字修饰
c++代码:
#include <stdio.h>
int main(int argc, char** argv)
{auto sk = argc;int a = 11 << sk;int b = 19 + argc;volatile int rv = a + b * 8;rv *= sk;return rv;
}
反汇编代码:
00007FF7F4102993 mov eax,dword ptr [argc]
00007FF7F4102999 mov dword ptr [sk],eax
00007FF7F410299C mov eax,dword ptr [sk]
00007FF7F410299F mov ecx,0Bh
00007FF7F41029A4 mov dword ptr [rbp+134h],ecx
00007FF7F41029AA movzx ecx,al
00007FF7F41029AD mov eax,dword ptr [rbp+134h]
00007FF7F41029B3 shl eax,cl
00007FF7F41029B5 mov dword ptr [a],eax
00007FF7F41029B8 mov eax,dword ptr [argc]
00007FF7F41029BE add eax,13h
00007FF7F41029C1 mov dword ptr [b],eax
00007FF7F41029C4 mov eax,dword ptr [a]
00007FF7F41029C7 mov ecx,dword ptr [b]
00007FF7F41029CA lea eax,[rax+rcx*8]
00007FF7F41029CD mov dword ptr [rv],eax
00007FF7F41029D0 mov eax,dword ptr [rv]
00007FF7F41029D3 imul eax,dword ptr [sk]
00007FF7F41029D7 mov dword ptr [rv],eax
00007FF7F41029DA mov eax,dword ptr [rv]
00007FF7F41029DD lea rsp,[rbp+148h]
00007FF7F41029E4 pop rdi
00007FF7F41029E5 pop rbp
00007FF7F41029E6 ret
VS Release环境MASM反汇编
没有使用volatile关键字修饰
反汇编代码:
00007FF748801000 mov eax,0Bh
00007FF748801005 shl eax,cl
00007FF748801007 lea eax,[rax+rcx*8]
00007FF74880100A add eax,98h
00007FF74880100F imul eax,ecx
00007FF748801012 ret
使用volatile关键字修饰
反汇编代码:
00007FF650C11005 shl eax,cl
00007FF650C11007 lea eax,[rax+rcx*8]
00007FF650C1100A add eax,98h
00007FF650C1100F mov dword ptr [rsp+8],eax
00007FF650C11013 mov eax,dword ptr [rv]
00007FF650C11017 imul eax,ecx
00007FF650C1101A mov dword ptr [rv],eax
00007FF650C1101E mov eax,dword ptr [rv]
00007FF650C11022 ret
Linux GUN x86 64bit AT&T 环境优化参数O1反汇编
没有使用volatile关键字修饰
c++源码:
#include <stdio.h>
int main(int argc, char** argv)
{auto sk = argc;int a = 11 << sk;int b = 19 + argc;int rv = a + b * 8;rv *= sk;return rv;
}
反汇编代码:
0000 89F9 movl %edi, %ecx
0002 B80B0000 movl $11, %eax
0007 D3E0 sall %cl, %eax
0009 8D84F898 leal 152(%rax,%rdi,8), %eax
0010 0FAFC7 imull %edi, %eax
0013 C3 ret
使用volatile关键字修饰
c++源码:
#include <stdio.h>
int main(int argc, char** argv)
{auto sk = argc;int a = 11 << sk;int b = 19 + argc;volatile int rv = a + b * 8;rv *= sk;return rv;
}
反汇编代码:
0000 89F9 movl %edi, %ecx
0002 B80B0000 movl $11, %eax
0007 D3E0 sall %cl, %eax
0009 8D84F898 leal 152(%rax,%rdi,8), %eax
0010 894424FC movl %eax, -4(%rsp)
0014 8B4424FC movl -4(%rsp), %eax
0018 0FAFC7 imull %edi, %eax
001b 894424FC movl %eax, -4(%rsp)
001f 8B4424FC movl -4(%rsp), %eax
0023 C3 ret
总结:
由上面的这些代码可以看到,非Debug环境有优化,但是因为volatile关键字的作用,有没有volatile关键字,优化后的汇编指令是不一样的。
关于Linux下AT&T格式汇编的详情请见: Linux c++反汇编源码细节解释说明_含影的博客-CSDN博客
如果使用GDB在Linux调试,GDB下载地址为: Index of /gnu/gdb
相关文章:
关于c++中mutable、const、volatile这三个关键字及对应c++与汇编示例源码
这哥三之间的关系是有趣的,不妨看看这个: cv (const and volatile) type qualifiers - cppreference.com mutable permits modification of the class member declared mutable even if the containing object is declared const. 即便一个对象是con…...
把大模型装进手机,分几步?
点击关注 文 | 姚 悦 编 | 王一粟 大模型“跑”进手机,AI的战火已经从“云端”烧至“移动终端”。 “进入AI时代,华为盘古大模型将会来助力鸿蒙生态。”8月4日,华为常务董事、终端BG CEO、智能汽车解决方案BU CEO 余承东介绍,…...
c++游戏制作指南(三):c++剧情类文字游戏的制作
🍿*★,*:.☆( ̄▽ ̄)/$:*.★* 🍿 🍟欢迎来到静渊隐者的csdn博文,本文是c游戏制作指南的一部🍟 🍕更多文章请点击下方链接🍕 🍨 c游戏制作指南dz…...
Flutter系列文章-实战项目
在本篇文章中,我们将通过一个实际的 Flutter 应用来综合运用最近学到的知识,包括保存到数据库、进行 HTTP 请求等。我们将开发一个简单的天气应用,可以根据用户输入的城市名获取该城市的天气信息,并将用户查询的城市列表保存到本地…...
HCIA---TCP/UDP协议
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 目录 文章目录 一.UDP协议简介 UDP协议的特点: 二.TCP协议简介 TCP协议特点 三.TCP和UDP的区别 思维导图 一.UDP协议简介 UDP(User …...
数据库索引的使用
1、MySQL的基本架构 架构图 左边的client可以看成是客户端,客户端有很多,像我们经常你使用的CMD黑窗口,像我们经常用于学习的WorkBench,像企业经常使用的Navicat工具,它们都是一个客户端。右边的这一大堆都可以看成是…...
校验 GPT-4 真实性的三个经典问题:快速区分 GPT-3.5 与 GPT-4,并提供免费测试网站
现在已经有很多 ChatGPT 的套壳网站,以下分享验明 GPT-4 真身的三个经典问题,帮助你快速区分套壳网站背后到底用的是 GPT-3.5 还是 GPT-4。 大家可以在这个网站测试:https://ai.hxkj.vip,免登录可以问三条,登录之后无限…...
SpringBoot整合MongoDB连接池(含源码)
💡版本依赖 jdk 17 SpringBoot 3.1.0 Mongo 6.0.8 mybatis-plus 2.0.2 💡环境准备 🌵MongoDB安装 安装教程请查看:一文搞定(linuxwindowsdocker)安装MongoDB 🌵导入依赖 <parent><groupId>org.sp…...
[oeasy]python0082_[趣味拓展]控制序列_清屏_控制输出位置_2J
光标位置 回忆上次内容 上次了解了键盘演化的过程 ESC 从 组合键到 独立按键 ESC的作用 是 进入 控制序列配置 控制信息控制信息 \033[y;xH 设置光标位置\033[2J 清屏 这到底怎么控制???🤔谁来实现这些功能? 控制…...
Zookeeper+kafka
目录 1. Zookeeper定义 2. Zookeeper工作机制 3. Zookeeper特点 4. Zookeeper数据结构 5. Zookeeper应用场景 5.1 统一命名服务 5.2 统一配置管理 5.3 统一集群管理 5.4 服务器动态上下线 5.5 软负载均衡 6. Zookeeper 选举机制 6.1 第一次启动选举机制 6.2 非第一…...
Gpt微信小程序搭建的前后端流程 - 前端小程序部分-1.基础页面框架的静态设计(二)
Gpt微信小程序搭建的前后端流程 - 前端小程序部分-1.基础页面框架的静态设计(二) 在开始这个专栏,我们需要找一个小程序为参考,参考和仿照其界面,聊天交互模式。 这里参考小程序-小柠AI智能聊天,可自行先体验。 该小程序主要提供了…...
Flask进阶:构建RESTful API和数据库交互
在初级教程中,我们已经介绍了如何使用Flask构建基础的Web应用。在本篇中级教程中,我们将学习如何用Flask构建RESTful API,以及如何使用Flask-SQLAlchemy进行数据库操作。 一、构建RESTful API REST(Representational State Tran…...
6.9(Java)二叉搜索树
1.我的代码: public class BinarySearchTree {class TreeNode {public int key;public TreeNode left;public TreeNode right;public TreeNode(int key) {this.key key;}}public TreeNode root; // 根节点// 插入一个元素,注意,不能插入重复的值,如…...
洛谷P2256 一中校运会之百米跑
题目背景 在一大堆秀恩爱的 ** 之中,来不及秀恩爱的苏大学神踏着坚定(?)的步伐走向了 100 100 100 米跑的起点。这时苏大学神发现,百米赛跑的参赛同学实在是太多了,连体育老师也忙不过来。这时体育老师发…...
python-opencv对极几何 StereoRectify
OpenCV如何正确使用stereoRectify函数 函数介绍 用于双目相机的立体校正环节中,这里只谈谈这个函数怎么使用,参数具体指哪些函数参数 随便去网上一搜或者看官方手册就能得到参数信息,但是!!相对关系非常容易出错&…...
pom文件---maven
027-Maven 命令行-实验四-生成 Web 工程-执行生成_ev_哔哩哔哩_bilibili 27节.后续补充 一.maven下载安装及配置 1)maven下载 2) settings文件配置本地仓库 3)settings配置远程仓库地址 4)配置maven工程的基础JDK版本 5)确认JDK环境变量配置没问题,配置maven的环境变量 验证…...
界面控件DevExpress.Drawing图形库早期增强功能分享
众所周知,DevExpress在v22.2发布周期中引入了全新的DevExpress.Drawing图形库(并且已经在随后的小更新中引入了一系列增强功能)。 在这篇博文中,我们将总结在DevExpress v23.1中解决的一些问题,以及在EAP构建中为以下…...
Semantic Kernel 入门系列:Connector连接器
当我们使用Native Function的时候,除了处理一些基本的逻辑操作之外,更多的还是需要进行外部数据源和服务的对接,要么是获取相关的数据,要么是保存输出结果。这一过程在Semantic Kernel中可以被归类为Connector。 Connector更像是…...
Maven介绍-下载-安装-使用-基础知识
Maven介绍-下载-安装-使用-基础知识 Maven的进阶高级用法可查看这篇文章: Maven分模块-继承-聚合-私服的高级用法 文章目录 Maven介绍-下载-安装-使用-基础知识01. Maven1.1 初识Maven1.1.1 什么是Maven1.1.2 Maven的作用 02. Maven概述2.1 Maven介绍2.2 Maven模型…...
Ansible环境搭建,CentOS 系列操作系统搭建Ansible集群环境
Ansible是一种自动化工具,基于Python写的,原理什么的就不过多再说了,详情参考:https://www.itwk.cc/post/403.html https://blog.csdn.net/qq_34185638/article/details/131079320?spm1001.2014.3001.5502 环境准备 HOSTNAMEIP…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
服务器硬防的应用场景都有哪些?
服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式,避免服务器受到各种恶意攻击和网络威胁,那么,服务器硬防通常都会应用在哪些场景当中呢? 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
【无标题】湖北理元理律师事务所:债务优化中的生活保障与法律平衡之道
文/法律实务观察组 在债务重组领域,专业机构的核心价值不仅在于减轻债务数字,更在于帮助债务人在履行义务的同时维持基本生活尊严。湖北理元理律师事务所的服务实践表明,合法债务优化需同步实现三重平衡: 法律刚性(债…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
