【问题标题】:Why is volatile deprecated in C++20?为什么在 C++20 中不推荐使用 volatile?
【发布时间】:2020-04-01 01:50:59
【问题描述】:

根据cppreferencevolatile 关键字的大多数用途将在 C++20 中被弃用。 volatile的缺点是什么?不使用volatile时的替代解决方案是什么?

【问题讨论】:

  • volatile 的某些用途未被弃用,因为它们很有用(例如,在直接从指定内存位置加载或存储的代码中,例如在设备驱动程序中)。相当多的“不推荐使用”与使用太多程序员使用的功能的能力有关 - 错误地 - 作为使变量访问原子的手段。现在的 C++ 库(自 C++11 起)提供了确保对变量进行原子访问的正确方法,因此在意图是原子访问时阻止程序员错误地使用 volatile 是有意义的。
  • @Peter volatile 的哪些典型用法不正确?

标签: c++ volatile c++20


【解决方案1】:

C++ committee language evolution chair 就原因进行了很好的讨论。

简单总结一下,volatile 被删除的地方在标准中没有任何明确的含义,只是造成了混乱。


激励(模棱两可)的例子

  • 易失位字段应由您的硬件手册和/或编译器指定。
  • += 是单个/原子指令吗? ++ 怎么样?
  • compare_exchange 需要多少次读取/写入?如果失败了怎么办?
  • void foo(int volatile n) 是什么意思?或int volatile foo()?
  • 应该*vp; 做负载吗? (这在标准中改变了两次。)

线程

历史上,人们使用volatile 来实现 C 和 C++ 中的线程安全。在 C++11 中,添加了在线程之间创建同步和共享状态的非 UB 方法。我推荐Back to Basics: Concurrency 作为一个很好的介绍。

【讨论】:

  • 我似乎无法弄清楚他们是否在弃用 volatile 限定的方法。按照drdobbs.com/cpp/volatile-the-multithreaded-programmers-b/… 的方式编写“不稳定的正确代码”是一个很好的模型。我希望他们的意图不是打破这种模式。
  • 其目的是强制使用 std::atomic 它将正确支持预减量和预增量 - 即通过正确使用原子指令。但是,当为多线程和非多线程使用编写通用代码时,它会导致 const_cast 变通方法,其中模板实现者必须将 volatile int (在非多线程编译中)转换为 int 以避免弃用警告。所以,烦人并导致额外的工作。\
  • 我想最后的问题是:std::atomic 是否检测到它何时不在多线程环境中编译,在这种情况下只需使用简单的递减和递增而不是原子操作性能可能会明显下降。
  • 我还假设std::atomic 不检查是否启用了线程;但是,这不是滥用volatile 进行线程处理的理由。 volatile 是/用于描述硬件何时可以与您的程序交互并且仅具有禁用优化器的效果,这不是它想要的含义。如果在单线程环境中优化 atomics 是一个严重的问题,我会要求您的编译器实现者将其作为一项功能。但是,我也想知道您为什么在单线程代码中使用同步功能。
  • 单线程代码中的引用计数支持对象在同时执行的不同算法之间重用。我曾在 dotcom 的航班搜索引擎上工作过——想象一下你想象过的最复杂的软件应用程序……我当然不知道在运行超快 C++ 的航班搜索服务器上可能会在 30 秒内发生什么。一切都经过专门设计,以尽可能快地运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-23
  • 2017-11-04
  • 2011-10-22
  • 2011-04-11
  • 2021-10-12
  • 2012-12-07
相关资源
最近更新 更多