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. plupload+struts2实现文件上传下载

    <%@ page language="java" import="java.util.*" pageEncoding="utf-8" ...

  2. 第二十六篇、因为自定item(nav)而使系统右滑返回手势失效的解决方法

    @interface ViewController () <uigesturerecognizerdelegate> @end@implementation ViewController ...

  3. intellij idea社区版 & maven & git & tomcat/jetty 的struts2项目的搭建

    1.新建一个project,并在project下新建一个maven module.

  4. 02_setter注入

    工程截图如下 [HelloWorld.java] package com.HigginCui; public class HelloWorld { private String words; publ ...

  5. mysql学习笔记3

    要用php+mysql 首先要配置环境.现在要先下载wamp(Windows下的Apache+Mysql/MariaDB+Perl/PHP/Python).直接安装就行 可以点下一步的就点下一步,直至 ...

  6. [getLongestLength] 加和为0的最长子串长度

    点击这里查看原文 假设一个数组仅仅由1和-1组成,求该数组的和为0的最长子串的长度. 例如: {1,-1,1,-1,1,1,1} 输出:4. 昨天机试的时候做到这道题,不会做,今天思考一下. 普通的解 ...

  7. C++ IO 详细用法

    http://www.cnblogs.com/keam37/ keam所有 转载请注明出处 本文将分别从<iostream>,<sstream>,<fstream> ...

  8. Pulltorefresh使用中碰到的问题

    第一 在使用XScrollView布局是,无法在该布局.xml文件,放置内容布局控件,假如放置了会报错, <com.markmao.pulltorefresh.widget.XScrollVie ...

  9. RabbitMQ RPC问题

    1.服务器端代码:https://github.com/rabbitmq/rabbitmq-tutorials/blob/master/python/rpc_server.py 2.客户端代码:htt ...

  10. debian 学习记录-5

    后裔排名 1 Debian - 1292 Fedora - 633 Knoppix - 50 (Knoppix本身是Debian后裔) Debian4 SuSE - 28 Debian,由Ian Mu ...