C++ -volatile在应用于方法时代表什么?

pinkon5k  于 2023-08-09  发布在  其他
关注(0)|答案(3)|浏览(108)

如果我有一个C++方法声明如下:

class A
{
public:
   double getPrice() volatile;
};

字符串

  1. volatile在这里代表什么?
    1.它能用来做什么?
    您可能会对Andrei Alexandrescu的this Dr Dobbs文章感兴趣。I was:)

**编辑:**这篇文章是写了一段时间,现在看来,社区已经继续前进。Herb Sutter说this。谢谢伊恩(和赫伯!)

@metal指出,Andrei有一篇后续文章here,他继续倡导使用volatile正确性作为一种有价值的工具,用于检测支持POSIX类互斥锁的系统上的竞争条件。

9jyewag0

9jyewag01#

您可能熟悉const方法和const-correctness(参见Sutter和Alexandrescu在 * C++ Coding Standards * 中的“Item 15 - Use const propagetely”),volatile以类似但略有不同的方式工作,以产生所谓的“volatile-correctness”。
const一样,volatile也是一个类型修饰符。当附加到一个成员函数时,如在您的示例中,修饰符(或两者都有!)意味着调用方法的对象必须具有该类型或可转换为该类型。
请考虑:

struct A
{
  void f();
  void cf() const;
  void vf() volatile;
  void cvf() const volatile;
  // ...
};

void foo( A& a, const A& ca, volatile A& va, const volatile A& cva )
{
  a.f();    // Ok
  a.cf();   // Ok: Can convert non-const    obj to const    obj
  a.vf();   // Ok: Can convert non-volatile obj to volatile obj
  a.cvf();  // Ok: Can convert non-cv       obj to cv       obj

  ca.f();   // Error: can't call non-const method on const obj
  ca.cf();  // Ok
  ca.vf();  // Error: can't call non-const method on const obj
  ca.cvf(); // Ok: Can convert

  va.f();   // Error: can't call non-volatile method on volatile obj
  va.cf();  // Error: can't call non-volatile method on volatile obj
  va.vf();  // Ok
  va.cvf(); // Ok: Can convert

  cva.f();   // Error: can't call non-cv method on cv obj
  cva.cf();  // Error: can't call non-cv method on cv obj
  cva.vf();  // Error: can't call non-cv method on cv obj
  cva.cvf(); // Ok
}

字符串
请注意,这些是编译时错误,而不是运行时错误,这就是它的潜在用处所在。
常量正确性可以防止编译时的意外错误,并使代码“更容易理解,跟踪和推理”(Sutter和Alexandrescu)。volatile-correctness可以类似地起作用,但使用得少得多(注意,C++中的const_cast可以抛弃constvolatileconst volatile,但不是称之为cv_cast或类似名称,而是单独以const命名,因为它更常用于抛弃const)。
例如,在"volatile - Multithreaded Programmer's Best Friend"中,Andrei Alexandrescu给出了一些示例,说明如何使用此方法使编译器自动检测多线程代码中的竞争条件。它也有大量关于类型修饰符如何工作的解释,但也可以参见他在subsequent column中的后续评论。

  • 更新 *:

注意C11改变了const的含义。Thus sayeth the Sutter:“const现在真正意味着'只读,或安全的并发读取'-无论是真正的物理/位const,或内部同步,使任何实际的写入与任何可能的并发const访问同步,这样调用者就无法区分。”
在其他地方,he notes表示,虽然C
11已经添加了并发原语,但volatile仍然不是其中之一:“C++ volatile变量(在C#和Java等语言中没有类似的变量)总是超出了本文和任何其他关于内存模型和同步的文章的范围。这是因为C++ volatile变量与线程或通信无关,并且不与这些东西交互。相反,C++ volatile变量应该被视为进入语言之外的不同世界的门户-根据定义不遵守语言的内存模型的内存位置,因为该内存位置由硬件访问(例如,由子卡写入),具有多个地址,或者是“奇怪”的并且超出语言。因此,C++ volatile变量通常是关于同步的每一个准则的例外,因为它们总是固有的“活泼”和不可同步的使用正常的工具(互斥,原子等),更普遍地存在于所有正常的语言和编译器之外,包括它们通常不能被编译器优化。有关更多讨论,请参阅我的文章“volatile vs. volatile”。

lf5gs5x2

lf5gs5x22#

它是一个volatile成员,就像const成员只能在const对象上调用一样,只能在volatile对象上调用。
有什么用?好吧,全局volatile几乎没有什么用处(它经常被误解为适用于多线程- MT -编程,在C++中不是这样,例如参见http://www.drdobbs.com/high-performance-computing/212701484),volatile类对象甚至更没有用处。
IIRC A. Alexandrescu建议使用对volatile对象进行的类型检查来静态地确保一些对MT编程有用的属性(比如在调用成员函数之前已经获取了锁)。遗憾的是,我找不到文章了。(这里是:http://www.drdobbs.com/184403766
编辑:从评论中添加链接(他们也在问题中添加)。

agxfikkp

agxfikkp3#

在成员函数(唯一可以有cv限定符的函数)中,constvolatile有效地修改了this指针。因此,就像const成员函数只能通过const指针访问对象一样,volatile成员函数只能通过volatile指针访问对象。
volatile的非正式含义是对象可以由于程序外部的环境(例如内存MapI/O或共享内存)而更改。确切的意思是,对volatile数据的任何访问都必须在实际中完成,因为它是在代码中编写的,并且可能不会被优化或改变相对于其他volatile访问或I/O操作的顺序。
这意味着任何与volatile成员函数中的对象相关的操作都必须按照编写的顺序进行。
此外,volatile成员函数只能调用其他volatile(或const volatile)成员函数。
至于有什么用……坦白说,我现在也想不出什么好用。volatile对于某些数据对象是至关重要的,比如指向I/O寄存器的指针,但我想不出为什么volatile成员函数会有用。

相关问题