volatile限定符——C++讲解

本文介绍了C++中volatile关键字的使用背景和作用,包括保证多线程环境下变量的可见性和防止编译器优化。通过实例说明volatile如何确保共享变量的实时更新,并对比了volatile与const的区别,强调了自定义拷贝和赋值操作的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、使用volatile的背景

直接处理硬件的程序常常包含这样的数据元素,它们的值由程序直接控制之外的过程控制。举例如下 :

i、程序可能包含一个由系统时钟定时更新的变量。当对象的值可能在程序的控制或检测之外被心迹时,应该将该对象声明为volatile。告诉编译器不应对这样的变量进行优化。

ii、变量读取

volatile int i = 10;
int k = i;
这段代码如果没有加上volatile,它的执行过程是 i = 10, 10 ->reg寄存器,k = reg值,就是说,k=i实际上是从寄存器里读出来的。这样快捷高效,当然并不是每次都这样,因为寄存器有限。如果在10->reg寄存器的时候,i存储的内存变化了,也就是别的线程修改了i的值,k=i仍然会按照i=10来执行
加上volatile后,执行过程是 i = 10, k = *(int *)(&i); 它会从i的内存地址上去读,当然值会非常准确,但是效率会比从寄存器中读要慢很多。

iii、来自jave虚拟机中的参考

什么是主内存?为什么是在主内存中?先看看java的内存模型(JMM)中内存与线程的关系。 

这里写图片描述

 
图片来自《深入理解Java虚拟机》

JMM中的内存分为主内存和工作内存,其中主内存是所有线程共享的,而工作内存是每个线程独立分配的,各个线程的工作内存之间相互独立、互不可见。在线程启动的时候,虚拟机为每个内存分配了一块工作内存,不仅包含了线程内部定义的局部变量,也包含了线程所需要的共享变量的副本,当然这是为了提高执行效率,读副本的比直接读主内存更快。

那么对于volatile修饰的变量(共享变量)来说,在工作内存发生了变化后,必须要马上写到主内存中,而线程读取到是volatile修饰的变量时,必须去主内存中去获取最新的值,而不是读工作内存中主内存的副本,这就有效的保证了线程之间变量的可见性。

2、C++的简单举例运用(只是用,没讲实质)

i、用法类比const修饰符,可以声明volatile指针、指向volatile对象的指针以及指向volatile对象的volatile指针:

volatile int v;//v是一个volatile int
int* volatile vip;//vip是一个volatile指针,它指向int
volatile int* ivp;//ivp是一个指针,它指向一个volatile int
volatile int* volatile vivp;//vivp是一个volatile指针,它指向一个volatile int

int *ip = &v;//错误:必须使用指向volatile的指针
ivp = &v;//正确:ivp是一个指向volatile的指针
vivp = &v;//正确:vivp是一个指向volatile的volatile指针

ii、合成的拷贝对volatile对象无效

const和volatile的一个重要区别是我们不能使用合成的考贝/移动构造函数及赋值运算符初始化volatile对象或从volatile对象赋值。解释:因为合成的成员接受的形参类型是(非volatile)常量引用,显然不能把一个非volatile引用绑定到一个volatile对象上

如需拷贝、移动或赋值它的volatile对象,则该类必须自定义拷贝或移动操作。代码举例如下:

class Foo {
pubilc:
	Foo(const volatile Foo&);//从一个volatile对进行拷贝
	Foo& operator=(volatile const Foo&);//将一个volatile对象赋值给一个非volatile对象
	Foo& operator=(volatile const Foo&) volatile;//将一个volatile对象赋值给一个volatile对象
	//Foo类的剩余部分
};

参考博文:

https://blog.youkuaiyun.com/u011519624/article/details/63686701

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值