什么是volatile拷贝构造函数用于?

10

您能举一个例子来演示volatile复制构造函数的用法吗?可以是微不足道的或现实世界的例子。

我实在想不出来一个例子。


7
当你有易变对象时,你需要易变拷贝构造函数。因此问题归结为:什么情况下需要易变对象? - Nawaz
1个回答

8

正如@Nawaz已经指出的:

当你有易失性对象时,你需要易失性复制构造函数。因此,问题归结为:何时需要易失性对象?

使用volatile关键字的主要原因通常是禁用优化。如果你有像这样的东西:

bool flag = false;
if(!flag) {}

编译器会发现标志不能被更改,因此无需每次检查标志-因此不会检查。但是,如果您将标志变量设置为volatile,则会检查。

以下是volatile关键字最初用途的观点:link

简而言之,它最初用于通过MMIO访问硬件,这可能有些不寻常:

unsigned char* pControl = 0xff24 ;
*pControl = 0 ;
*pControl = 0 ;
*pControl = 0 ;

而且你不想因为优化而将这3个任务变成一个。

这里有一篇关于多线程软件中 volatile 的安德烈·亚历山大斯库的论文:link

有些文章批评了亚历山大斯库的论文,但我找不到了。那里的观点是他抛弃了 volatile 属性等。

请注意@JanHudec指出的多线程中非常重要的一点:

volatile 在多线程上下文中完全无用,因为虽然它可以防止优化,但它不会生成显式屏障。而没有这些屏障,某个 CPU 上进行的写操作可能对另一个 CPU 不可见(依赖于架构;x86 具有一致的高速缓存,因此写入始终可见)。

此外,volatile 不能强制执行操作为原子操作。在 x86 上分配总是原子操作,但不是所有 CPU 架构都是这样。而且像增量这样更复杂的操作只能使用 std::atomic 使其成为原子操作。


意见不可用,请尝试使用有效的永久链接。 - Zeta
3
在多线程环境中,volatile 是毫无用处的,因为它虽然可以防止优化,但它不会产生明确的屏障。如果没有这些屏障,在一个CPU上完成的写操作可能对另一个CPU不可见(依赖于架构;x86具有一致的缓存,因此写操作始终是可见的)。 - Jan Hudec
1
另外,volatile并不能强制操作具有原子性。在x86上,赋值操作始终是原子的,但并非所有CPU架构都是如此。而且,像增量这样更复杂的操作只能使用std::atomic使其具有原子性。 - Jan Hudec
@JanHudec 是的,我只是没有详细说明多线程,因为它不是常见的做法,备受批评,并且非常依赖于架构。但是我还是把它留在那里作为概述,因为在理论上它很有趣,这是我的观点。 - Wintermute
@StanMcGeek:不幸的是,我看到有人建议它适用于多线程,因此认为应该总是说它不适用。 - Jan Hudec

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接