如果我有一个C++方法声明如下:
class A
{
public:
double getPrice() volatile;
};
字符串
volatile
在这里代表什么?
1.它能用来做什么?
您可能会对Andrei Alexandrescu的this Dr Dobbs文章感兴趣。I was:)
**编辑:**这篇文章是写了一段时间,现在看来,社区已经继续前进。Herb Sutter说this。谢谢伊恩(和赫伯!)
@metal指出,Andrei有一篇后续文章here,他继续倡导使用volatile正确性作为一种有价值的工具,用于检测支持POSIX类互斥锁的系统上的竞争条件。
3条答案
按热度按时间9jyewag01#
您可能熟悉
const
方法和const-correctness(参见Sutter和Alexandrescu在 * C++ Coding Standards * 中的“Item 15 - Use const propagetely”),volatile
以类似但略有不同的方式工作,以产生所谓的“volatile-correctness”。和
const
一样,volatile
也是一个类型修饰符。当附加到一个成员函数时,如在您的示例中,修饰符(或两者都有!)意味着调用方法的对象必须具有该类型或可转换为该类型。请考虑:
字符串
请注意,这些是编译时错误,而不是运行时错误,这就是它的潜在用处所在。
常量正确性可以防止编译时的意外错误,并使代码“更容易理解,跟踪和推理”(Sutter和Alexandrescu)。volatile-correctness可以类似地起作用,但使用得少得多(注意,C++中的
const_cast
可以抛弃const
,volatile
或const 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表示,虽然C11已经添加了并发原语,但
volatile
仍然不是其中之一:“C++ volatile变量(在C#和Java等语言中没有类似的变量)总是超出了本文和任何其他关于内存模型和同步的文章的范围。这是因为C++ volatile变量与线程或通信无关,并且不与这些东西交互。相反,C++ volatile变量应该被视为进入语言之外的不同世界的门户-根据定义不遵守语言的内存模型的内存位置,因为该内存位置由硬件访问(例如,由子卡写入),具有多个地址,或者是“奇怪”的并且超出语言。因此,C++ volatile变量通常是关于同步的每一个准则的例外,因为它们总是固有的“活泼”和不可同步的使用正常的工具(互斥,原子等),更普遍地存在于所有正常的语言和编译器之外,包括它们通常不能被编译器优化。有关更多讨论,请参阅我的文章“volatile vs. volatile”。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)
编辑:从评论中添加链接(他们也在问题中添加)。
agxfikkp3#
在成员函数(唯一可以有cv限定符的函数)中,
const
或volatile
有效地修改了this
指针。因此,就像const
成员函数只能通过const
指针访问对象一样,volatile
成员函数只能通过volatile
指针访问对象。volatile
的非正式含义是对象可以由于程序外部的环境(例如内存MapI/O或共享内存)而更改。确切的意思是,对volatile
数据的任何访问都必须在实际中完成,因为它是在代码中编写的,并且可能不会被优化或改变相对于其他volatile
访问或I/O操作的顺序。这意味着任何与
volatile
成员函数中的对象相关的操作都必须按照编写的顺序进行。此外,
volatile
成员函数只能调用其他volatile
(或const volatile
)成员函数。至于有什么用……坦白说,我现在也想不出什么好用。
volatile
对于某些数据对象是至关重要的,比如指向I/O寄存器的指针,但我想不出为什么volatile
成员函数会有用。