const 和 mutable在C++存在已经很多年了,对于如今的这两个关键字你了解多少?

Problem

JG Question

1. 什么是“共享变量”?

Guru Question

2. const 和 mutable对于共享变量来说意味着什么?

3. 在C++98和C++11两者间,const 和 mutable有什么区别?

Stop and thinking……

Solution

1. 什么是“共享变量”?

共享变量是在同一时间可以被多个线程同时访问的变量。

这个概念在C++内存模型中很重要。例如:C++内存模型禁止创造一个写入“潜在共享变量区”,这不会被写入到程序执行的顺序一致(sequentially consistent)。当C++标准库禁止通过(其他)线程访问修改对象指的就是这节。

2. const 和 mutable对于共享变量来说意味着什么?
     从C++11开始,变量加上const可能共享对于并发来说,意思是“只读或几乎和只读一样”。在同一对象上的并发const操作要求在没有调用代码做外部同步是安全的。如果你在实现一个类型,除非你知道这个类型的对象绝不会被共享(通常不可能),这几意味着你的每一个const成员函数必须满足其下一点:

· 这个对象真正的是物理上/按位的const,意味着在对象的数据上不执行写动作;
   · 内部同步,这样如果在对象的数据上做了写的动作,那么数据可以通过mutex或者同等性质的(或者是atomic<>)来保证数据的正确性,因此任何可能多调用的并发const访问都不能辨别其中的差别。(相同的)

类型没有遵循以上任意其中一点,那么都不能和标准库一起使用。详细参照ISO C++ §17.6.5.9

同样地,在mutable的成员变量上写总意味着:此变量是“可写的但逻辑上是const的”。这意味着:

·“逻辑上const”部分的意思是“可以被多个并发const操作安全地使用”;
       ·”mutable“和”可写性“部分的意思是一些const操作可能确实会对共享变量进行写的动作,这意味着在对变量进行读和写是内在正确的,因此它应该使用mutex或相同的东西来保护,或者使用atomic<>。

通常情况下:

Guideline:记住”M&M规则“:对于成员变量来说,mutable和mutex(或atomic)是一起使用的。

这是双向的,也就是:
     ·(1)对于成员变量,mutable意味着mutex(或等价物):一个mutable的成员变量假定是一个可变的共享变量,因此必须是内在同步的,使用mutex,称atomic或者同类的东西来保护。
     ·(2)对于成员变量,mutex(或同等的同步类型)意味着mutable:一个成员变量它本身是同步类型,比如mutex或条件变量(condition variable),自然地需要mutable,因为你可能会在并发的const成员函数中以非const的方式来使用它(比如:使用std::lock_guard<mutex>)

我们或在GotW #6b的第二部分看到例子。

3. 在C++98和C++11两者间,const 和 mutable有什么区别?

首先澄清一点:C++98单线程代码依旧是能正常运行的。C++11对C++98有相当好的兼容,即使是在const的语义上有着进化。C++98单线程代码使用老的”逻辑const“意味着const依然是有效的。

随着C++98,我们告诫一整代C++开发者,”const意味的是逻辑上的const,不是物理上/按位的const“。这也就是,在C++98中,我们教授的是const只意味着对象的可观察状态(就是说,通过非private成员函数)不应该改变直到调用者调用。但是它的内部位可能是改变了的,为了更新计数器和一些设施,其他数据通过类型的public或protected接口是不能访问的。

这些定义对于并发来说是不够的。在C++11和之后的版本中,标准库中包含了并发的内存模型和线程安全规范。这也使得更简单一些:现在const真的是意味着”只读“或安全的并发读取,要不真正在物理上/按位const,或者内部同步。因此对于任意可能的并发const访问的写都是同步的,这样调用者就不会知道其中存在不同。

尽管已存在的C++98年代的类型在C++98年代的单线程中依旧能运行正常,这些类型和一些你现在所编写的类型都应该遵循新的更严格的要求,如果它们可能用在多线程中。好消息是那么已经存在的类型已经遵循了这个规则。在单线程中依赖于强制去掉const和/或使用mutable的数据成员已经被普遍质疑和罕见。

原文地址:http://herbsutter.com/2013/05/24/gotw-6a-const-correctness-part-1-3/

[译]GotW #6a: Const-Correctness, Part 1的更多相关文章

  1. [译]GotW #6b Const-Correctness, Part 2

         const和mutable对于书写安全代码来说是个很有利的工具,坚持使用它们. Problem Guru Question 在下面代码中,在只要合适的情况下,对const进行增加和删除(包括 ...

  2. [译]GotW #4 Class Mechanics

    你对写一个类的细节有多在行?这条款不仅注重公然的错误,更多的是一种专业的风格.了解这些原则将会帮助你设计易于使用和易于管理的类. JG Question 1. 什么使得接口“容易正确使用,错误使用却很 ...

  3. [译]GotW #3: Using the Standard Library (or, Temporaries Revisited)

    高效的代码重用是良好的软件工程中重要的一部分.为了演示如何更好地通过使用标准库算法而不是手工编写,我们再次考虑先前的问题.演示通过简单利用标准库中已有的算法来避免的一些问题. Problem JG Q ...

  4. [译]GotW #2: Temporary Objects

        不必要的和(或)临时的变量经常是罪魁祸首,它让你在程序性能方面的努力功亏一篑.如何才能识别出它们然后避免它们呢? Problem JG Question: 1. 什么是临时变量? Guru Q ...

  5. [译]GotW #89 Smart Pointers

    There's a lot to love about standard smart pointers in general, and unique_ptr in particular. Proble ...

  6. [译]GotW #1: Variable Initialization 续

    Answer 2. 下面每行代码都做了什么? 在Q2中,我们创建了一个vector<int>且传了参数10和20到构造函数中,第一种情况下(10,20),第二种情况是{10, 20}. 它 ...

  7. [译]GotW #1: Variable Initialization

    原文地址:http://herbsutter.com/2013/05/09/gotw-1-solution/ 第一个问题强调的是要明白自己在写什么的重要性.下面有几行简单的代码--它们大多数之间都有区 ...

  8. [译]GotW #5:Overriding Virtual Functions

       虚函数是一个很基本的特性,但是它们偶尔会隐藏在很微妙的地方,然后等着你.如果你能回答下面的问题,那么你已经完全了解了它,你不太能浪费太多时间去调试类似下面的问题. Problem JG Ques ...

  9. Meaning of “const” last in a C++ method declaration?

    函数尾部的const是什么意思? 1 Answer by Jnick Bernnet A "const function", denoted with the keyword co ...

随机推荐

  1. Agile.Net 组件式开发平台 - 开发环境部署

    环境准备: Windows 7 (32/64) Windows Server 2008 (32/64) Microsoft SQL Server 2008 R2 (32/64) Microsoft V ...

  2. iOS中 常用的mac终端指令

    1.使用caffeinate阻止Mac运行屏幕保护和睡眠 caffeinate能阻止Mac进入睡眠状态,而且屏幕保护也不会激活.我们最好使用-t为命令加入具体的时间.比如下面的命令可以使Mac一小时内 ...

  3. 使用SQL Server 2005 新的语法ROW_NUMBER()进行分页的两种不同方式的性能比较

    相比在SQL Server 2000 中使用的分页方式,在SQL Server 2005中使用新的语法ROW_NUMBER()来分页效率要高出很多,但是很多人在使用ROW_NUMBER()这种分页方式 ...

  4. 九度OJ 1510 替换空格

    题目地址:http://ac.jobdu.com/problem.php?pid=1510 题目描述: 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We ...

  5. Github上关于大数据的开源项目、论文等合集

    https://github.com/onurakpolat/awesome-bigdata

  6. 通过 ANE(Adobe Native Extension) 启动Andriod服务 推送消息(四)

    这一节,是要把AS库和Android的jar包及相关配置文件打成一个ane包. 首先先建一个build目录,里面文件目录结构如下: 然后用打开压缩包的方式打开ServiceLib.swc, 把其中的l ...

  7. Beyond Compare 使用介绍

    Beyond Compare 背景 平时工作中对于源代码都是使用SVN来管理,在线状态下工作的很好,但是有时候离线状态下,对于多个版本之间的代码合并就比较麻烦.尤其是涉及到多人协作时更是如此. 所以找 ...

  8. 用 BPL 封装数据连接

    BPL 代码: uDM.pas unit uDM; interface uses SysUtils, Classes, uIntf, DB, ABSMain; type TDM = class(TDa ...

  9. Python 列表实现字典的get功能

    字典有一个很好用的方法,就是get,既可以预防KeyError异常,也可以为不存在的key设置一个默认的value 例如: v=d.get('k','default') 而列表没有一个类似的方法,如果 ...

  10. linux系统管理

    系统 # uname -a               # 查看内核/操作系统/CPU信息# head -n 1 /etc/issue   # 查看操作系统版本# cat /proc/cpuinfo  ...