当前位置: 首页 > 编程日记 > 正文

C++中关键字volatile和mutable用法

C/C++中的volatile关键字和const对应,用来修饰变量,用于告诉编译器该变量值是不稳定的,可能被更改。使用volatile注意事项:

(1). 编译器会对带有volatile关键字的变量禁用优化(A volatile specifier is a hint to a compiler that an object may change its value in ways not specified by the language so that aggressive optimizations must be avoided)。

(2). 当多个线程都要用到某一个变量且该变量的值会被改变时应该用volatile声明,该关键字的作用是防止编译器优化把变量从内存装入CPU寄存器中。如果变量被装入寄存器,那么多个线程有可能有的使用内存中的变量,有的使用寄存器中的变量,这会造成程序的错误执行。volatile的意思是让编译器每次操作该变量时一定要从内存中取出,而不是使用已经存在寄存器中的值(It cannot cache the variables in register)。

(3). 中断服务程序中访问到的变量最好带上volatile。

(4). 并行设备的硬件寄存器的变量最好带上volatile。

(5). 声明的变量可以同时带有const和volatile关键字。

(6). 多个volatile变量间的操作,是不会被编译器交换顺序的,能够保证volatile变量间的顺序性,编译器不会进行乱序优化(The value cannot change in order of assignment)。但volatile变量和非volatile变量之间的顺序,编译器不保证顺序,可能会进行乱序优化。

C++中的mutable关键字使用场景:

(1). 允许即使包含它的对象被声明为const时仍可修改声明为mutable的类成员(sometimes there is requirement to modify one or more data members of class/struct through const function even though you don’t want the function to update other members of class/struct. This task can be easily performed by using mutable keyword)。

(2). 应用在C++11 lambda表达式来表示按值捕获的值是可修改的,默认情况下是不可修改的,但修改仅在lambda式内有效(since c++11 mutable can be used on a lambda to denote that things captured by value are modifiable (they aren't by default))。

详细用法见下面的测试代码,下面是从其他文章中copy的测试代码,详细内容介绍可以参考对应的reference:

#include "volatile_mutable.hpp"
#include <iostream>
#include <stdio.h>
#include <time.h>
#include <mutex>
#include <string.h>namespace volatile_mutable_ {///
int test_volatile_1()
{volatile int i1 = 0; // correctint volatile i2 = 0; // correctreturn 0;
}///
// reference: https://en.cppreference.com/w/c/language/volatile
int test_volatile_2()
{
{ // Any attempt to read or write to an object whose type is volatile-qualified through a non-volatile lvalue results in undefined behaviorvolatile int n = 1; // object of volatile-qualified typeint* p = (int*)&n;int val = *p; // undefined behavior in C, Note: link does not report an error under C++fprintf(stdout, "val: %d\n", val);
}{ // A member of a volatile-qualified structure or union type acquires the qualification of the type it belongs totypedef struct ss { int i; const int ci; } s;// the type of s.i is int, the type of s.ci is const intvolatile s vs = { 1, 2 };// the types of vs.i and vs.ci are volatile int and const volatile int
}{ // If an array type is declared with the volatile type qualifier (through the use of typedef), the array type is not volatile-qualified, but its element type istypedef int A[2][3];volatile A a = { {4, 5, 6}, {7, 8, 9} }; // array of array of volatile int//int* pi = a[0]; // Error: a[0] has type volatile int*volatile int* pi = a[0];
}{ // A pointer to a non-volatile type can be implicitly converted to a pointer to the volatile-qualified version of the same or compatible type. The reverse conversion can be performed with a cast expressionint* p = nullptr;volatile int* vp = p; // OK: adds qualifiers (int to volatile int)//p = vp; // Error: discards qualifiers (volatile int to int)p = (int*)vp; // OK: cast
}{ // volatile disable optimizationsclock_t t = clock();double d = 0.0;for (int n = 0; n < 10000; ++n)for (int m = 0; m < 10000; ++m)d += d * n*m; // reads and writes to a non-volatile fprintf(stdout, "Modified a non-volatile variable 100m times. Time used: %.2f seconds\n", (double)(clock() - t) / CLOCKS_PER_SEC);t = clock();volatile double vd = 0.0;for (int n = 0; n < 10000; ++n)for (int m = 0; m < 10000; ++m)vd += vd * n*m; // reads and writes to a volatile fprintf(stdout, "Modified a volatile variable 100m times. Time used: %.2f seconds\n", (double)(clock() - t) / CLOCKS_PER_SEC);
}return 0;
}///
// reference: https://en.cppreference.com/w/cpp/language/cv
int test_volatile_3()
{int n1 = 0;           // non-const objectconst int n2 = 0;     // const objectint const n3 = 0;     // const object (same as n2)volatile int n4 = 0;  // volatile objectconst struct {int n1;mutable int n2;} x = { 0, 0 };      // const object with mutable membern1 = 1; // ok, modifiable object//n2 = 2; // error: non-modifiable objectn4 = 3; // ok, treated as a side-effect//x.n1 = 4; // error: member of a const object is constx.n2 = 4; // ok, mutable member of a const object isn't constconst int& r1 = n1; // reference to const bound to non-const object//r1 = 2; // error: attempt to modify through reference to constconst_cast<int&>(r1) = 2; // ok, modifies non-const object n1fprintf(stdout, "n1: %d\n", n1); // 2const int& r2 = n2; // reference to const bound to const object//r2 = 2; // error: attempt to modify through reference to constconst_cast<int&>(r2) = 2; // undefined behavior: attempt to modify const object n2, Note: link does not report an error under C++fprintf(stdout, "n2: %d\n", n2); // 0return 0;
}///
// reference: https://www.geeksforgeeks.org/understanding-volatile-qualifier-in-c/
int test_volatile_4()
{
{const int local = 10;int *ptr = (int*)&local;fprintf(stdout, "Initial value of local : %d \n", local); // 10*ptr = 100;fprintf(stdout, "Modified value of local: %d \n", local); // 10
}{const volatile int local = 10;int *ptr = (int*)&local;fprintf(stdout, "Initial value of local : %d \n", local); // 10*ptr = 100;fprintf(stdout, "Modified value of local: %d \n", local); // 100
}return 0;
}///
// reference: https://en.cppreference.com/w/cpp/language/cv
int test_mutable_1()
{// Mutable is used to specify that the member does not affect the externally visible state of the class (as often used for mutexes,// memo caches, lazy evaluation, and access instrumentation)class ThreadsafeCounter {public:int get() const {std::lock_guard<std::mutex> lk(m);return data;}void inc() {std::lock_guard<std::mutex> lk(m);++data;}private:mutable std::mutex m; // The "M&M rule": mutable and mutex go togetherint data = 0;};return 0;
}///
// reference: https://www.tutorialspoint.com/cplusplus-mutable-keyword
int test_mutable_2()
{class Test {public:Test(int x = 0, int y = 0) : a(x), b(y) {}void seta(int x = 0) { a = x; }void setb(int y = 0) { b = y; }void disp() { fprintf(stdout, "a: %d, b: %d\n", a, b); }public:int a;mutable int b;};const Test t(10, 20);fprintf(stdout, "t.a: %d, t.b: %d \n", t.a, t.b); // 10, 20//t.a=30; // Error occurs because a can not be changed, because object is constant.t.b = 100; // b still can be changed, because b is mutable.fprintf(stdout, "t.a: %d, t.b: %d \n", t.a, t.b); // 10, 100return 0;
}///
// reference: https://www.geeksforgeeks.org/c-mutable-keyword/
int test_mutable_3()
{using std::cout;using std::endl;class Customer {public:Customer(char* s, char* m, int a, int p){strcpy(name, s);strcpy(placedorder, m);tableno = a;bill = p;}void changePlacedOrder(char* p) const { strcpy(placedorder, p); }void changeBill(int s) const { bill = s; }void display() const{cout << "Customer name is: " << name << endl;cout << "Food ordered by customer is: " << placedorder << endl;cout << "table no is: " << tableno << endl;cout << "Total payable amount: " << bill << endl;}private:char name[25];mutable char placedorder[50];int tableno;mutable int bill;};const Customer c1("Pravasi Meet", "Ice Cream", 3, 100);c1.display();c1.changePlacedOrder("GulabJammuns");c1.changeBill(150);c1.display();return 0;
}///
// reference: https://stackoverflow.com/questions/105014/does-the-mutable-keyword-have-any-purpose-other-than-allowing-the-variable-to
int test_mutable_4()
{int x = 0;auto f1 = [=]() mutable { x = 42; }; // OK//auto f2 = [=]() { x = 42; }; // Error: a by-value capture cannot be modified in a non-mutable lambdafprintf(stdout, "x: %d\n", x); // 0return 0;
}} // namespace volatile_mutable_

GitHub:https://github.com/fengbingchun/Messy_Test

相关文章:

基于生成对抗网络(GAN)的人脸变形(附链接) | CSDN博文精选

扫码参与CSDN“原力计划”翻译 | 张一豪校对 | 吴金笛来源 | 数据派THU*点击阅读原文&#xff0c;查看「CSDN原力计划」详细说明。本文详细介绍了生成对抗网络&#xff08;GAN&#xff09;的知识&#xff0c;并用其变换人脸&#xff0c;并探寻如何利用StyleGAN生成不同属性&…

Jmeter连接Oracle数据库

一、Jmeter要连接oracle数据库&#xff0c;就必须复制JDBC驱动jar包文件ojdbc14.jar到Jmeter的lib目录下二、进入Jmeter的bin目录运行Jmeter.bat&#xff0c;启动Jmeter三、Jmeter软件配置如下&#xff1a;1、添加线程组右击线程组&#xff0c;选择“添加--配置元件--JDBC Conn…

swift3.0友盟分享

经过&#xff08;一&#xff09;的讲解&#xff0c;大家应该可以按照友盟提供的测试账号可以集成友盟分享了&#xff0c;友盟目前集合了18个APP共27种分享&#xff0c;可以授权的有10个App&#xff1a;微信、QQ、新浪微博、腾讯微博、人人网、豆瓣、Facebook、Twitter、Linkedi…

C++11中std::future的使用

C11中的std::future是一个模板类。std::future提供了一种用于访问异步操作结果的机制。std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::shared_future相反)( std::future references shared state that is not shared with any other asynchronous retur…

给算法工程师和研究员的「霸王餐」| 附招聘信息

现在的算法工程师真的是太难了&#xff01;要让AI会看人眼都分辨不清的医疗影像&#xff01;数据又不够&#xff0c;还得用前沿技术&#xff01;好不容易学会看片&#xff0c;还要让AI会分析病理&#xff01;然后模型搞出来了&#xff0c;还要把几十种模型&#xff0c;做N次计算…

swift3.0三种反向传值

一 :通知 1.通知传值所用方法 // MARK: - private methods(内部接口) let NotifMycation NSNotification.Name(rawValue:"MyNSNotification") func tempbuttonAction() { //这个方法可以传一个值 NotificationCenter.default.post(name: NotifMycation, object: &q…

C++11中std::shared_future的使用

C11中的std::shared_future是个模板类。与std::future类似&#xff0c;std::shared_future提供了一种访问异步操作结果的机制&#xff1b;不同于std::future&#xff0c;std::shared_future允许多个线程等待同一个共享状态&#xff1b;不同于std::future仅支持移动操作&#xf…

聊聊抖音、奈飞、Twitch、大疆、快手、B站的多媒体关键技术

随着5G牌照发放&#xff0c;5G终端正在迎来集中上市潮&#xff0c;对于5G带来的变革一触即发。目前互联网上超过七成的流量来自多媒体&#xff0c;未来这个比例将超过八成。音视频就像空气和水一样普及&#xff0c;深度到每个人的生活和工作中。同时&#xff0c;深度学习技术则…

Linux安全事件应急响应排查方法总结

Linux安全事件应急响应排查方法总结 Linux是服务器操作系统中最常用的操作系统&#xff0c;因为其拥有高性能、高扩展性、高安全性&#xff0c;受到了越来越多的运维人员追捧。但是针对Linux服务器操作系统的安全事件也非常多的。攻击方式主要是弱口令攻击、远程溢出攻击及其他…

C++11中std::packaged_task的使用

C11中的std::packaged_task是个模板类。std::packaged_task包装任何可调用目标(函数、lambda表达式、bind表达式、函数对象)以便它可以被异步调用。它的返回值或抛出的异常被存储于能通过std::future对象访问的共享状态中。 std::packaged_task类似于std::function&#xff0c…

Swift3.0和OC桥接方法

1.直接在工程中commandn&#xff0c;出现如图&#xff0c;点击Header File创建桥接文件Bridging-Header.h,如图&#xff1a; 2.点击next&#xff0c;出现如图画面&#xff0c;一定要记得勾选第一项&#xff0c;再点击create创建完成。 3.配置桥接文件&#xff0c;点击target - …

量子算命,在线掷筊:一个IBM量子云计算机的应用实践,代码都有了

整理 | Jane 出品| AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09; “算命”&#xff0c;古今中外&#xff0c;亘古不衰的一门学问&#xff0c;哪怕到了今天&#xff0c;大家对算命占卜都抱着一些”敬畏“的信任心理&#xff0c;西方流行塔罗牌&#xff0c;国…

rails应用ajax之二:使用rails自身支持

考虑另一种情况&#xff1a; 1. 页面上半部分显示当前的所有用户&#xff0c;页面下半部分是输入新用户的界面&#xff1b; 2. 每当输入新用户时&#xff0c;页面上半部分会动态更新新加用户的内容&#xff1b; 我们还是用ajax实现&#xff0c;不过这次用rails内部对ajax的支持…

C++11中std::async的使用

C11中的std::async是个模板函数。std::async异步调用函数&#xff0c;在某个时候以Args作为参数(可变长参数)调用Fn&#xff0c;无需等待Fn执行完成就可返回&#xff0c;返回结果是个std::future对象。Fn返回的值可通过std::future对象的get成员函数获取。一旦完成Fn的执行&…

BAT数据披露:缺人!110万AI人才缺口,两者矛盾,凉凉了!

人工智能到底有多火&#xff1f;近日国内首份《BAT人工智能领域人才发展报告》新鲜出炉&#xff0c;此次报告是针对国内人工智能领域的人才争夺情况进行了梳理。并把研究对象锁定在BAT三大巨头的身上。来源&#xff1a;《BAT人工智能领域人才发展报告》其中得出最为核心的结论&…

swift3.0最新拨打电话方法

let alertVC : UIAlertController UIAlertController.init(title: "是否拨打报警电话:10086", message: "", preferredStyle: .alert) let falseAA : UIAlertAction UIAlertAction.init(title: "取消", style: .cancel, handler: nil) let tr…

关于手机已处理里重复单据的处理办法

更新视图 VWFE_TASK去掉 union TWFE_TASK_BAK 的部分&#xff0c;原因是因为后面做了流程预演导致的问题转载于:https://blog.51cto.com/iderun/1602828

swiftswift3.0自己封装的快速构建页面的方法

//#param mark 控件 func creatLabel(frame:CGRect,text:String,textColor:UIColor,textFont:CGFloat,textAlignment:NSTextAlignment) -> UILabel { let label UILabel.init(frame: frame) label.text text label.textColor textColor label.font UIFont.systemFont(of…

Google是如何做Code Review的?| CSDN原力计划

作者 | 帅昕 xindoo 编辑 | 屠敏出品 | CSDN 博客我和几个小伙伴一起翻译了Google前一段时间放出来的Google’s Engineering Practices documentation&#xff08;https://github.com/google/eng-practices&#xff09;&#xff0c;翻译后的GitHub仓库&#xff1a;https://gith…

从FFmpeg 4. 2源码中提取dshow mjpeg code步骤

之前在https://blog.csdn.net/fengbingchun/article/details/103735560 中介绍过在Windows上通过vs2017编译FFmpeg源码进行单步调试的步骤&#xff0c;为了进一步熟悉FFmpeg这里以提取FFmpeg dshow mjpeg源码为例介绍其实现过程及注意事项&#xff1a; FFmpeg是用C实现的&…

ControlButton按钮事件

#ifndef __HControlButton_H__#define __HControlButton_H__#include "cocos2d.h"#include "cocos-ext.h"USING_NS_CC;USING_NS_CC_EXT; //用于标识当前按钮的状态typedef enum{ touch_begin, touch_down, touch_up,}tagForTouch;class HControlB…

swift3.0UIAlertController使用方法

let alertVC : UIAlertController UIAlertController.init(title: "添加照片", message: "", preferredStyle: .actionSheet) let cleanAction UIAlertAction(title: "取消", style: UIAlertActionStyle.cancel,handler:nil) let photoActi…

Doxygen使用介绍

Doxygen的主页为http://doxygen.nl/&#xff0c;它的license为GPL&#xff0c;最新发布版本为1.8.17&#xff0c;源代码存放在https://github.com/doxygen/doxygen&#xff0c;它支持的语言包括C、C、Objective-C、C#、Java、Python等&#xff0c;它支持的系统平台包括Winodws、…

云计算软件生态圈:摸到一把大牌

作者 | 老姜编辑 | 阿秃出品 | CSDN云计算&#xff08;ID&#xff1a;CSDNcloud&#xff09;“我觉得我摸着了一把大牌。”软件领域的新锐企业——有赞公司创始人兼CEO白鸦在转向SaaS领域的一个细分市场时&#xff0c;曾对天使投资人这样说。而老牌软件企业金蝶创始人徐少春在2…

iOS封装HTTPS双向和单向验证

1.HttpsUtil (1) 对双向和单向验证的封装 #import <Foundation/Foundation.h> #import "AFNetworking.h" interface HttpsUtil : NSObject // 双向认证 (void)configHTTPSessionManager:(AFHTTPSessionManager *)manager serverCers:(NSArray *) serverCerNam…

开源库BearSSL介绍及使用

BearSSL是用C语言实现的SSL/TLS协议&#xff0c;它的源码可直接通过git clone https://www.bearssl.org/git/BearSSL 下载&#xff0c;它的license是MIT&#xff0c;最新版本为0.6。 BearSSL的主要特性是&#xff1a; (1). 正确且安全&#xff1a;对不安全的协议版本和算法选…

个推CTO安森:我所理解的数据中台

作者 | 个推CTO安森来源 | 个推技术学院&#xff08;ID:ID: getuitech&#xff09;引言在前面两篇文章&#xff08;《数据智能时代来临&#xff1a;本质及技术体系要求》和《多维度分析系统的选型方法》&#xff09;之中&#xff0c;我们概括性地阐述了对于数据智能的理解&…

玩弹珠手游-杂想

前言 为什么会写这个杂想呢&#xff1f; 因为最近这一个月来&#xff0c;我有点太沉迷怪物弹珠这个游戏了&#xff0c;每天下班回来的时间和上下班路途都在玩这个游戏&#xff0c;占据了我大部分的业余时间&#xff0c;也该是时候放一放玩游戏了。 为什么会玩这个游戏呢&#x…

OC封装时间选择器

#import <UIKit/UIKit.h> protocol TimeDatePickerViewDelegate <NSObject> //必须实现的两个协议 required - (void)changeTime : (NSDate *)date;//当时改变时出发 - (void)daterMine : (NSDate *)date;//更确定时间 end interface TimeDatePickerView :UIView /…