我有一个A类,我重载了它的operator =。但是,我需要做这样的事情:
volatile A x;
A y;
x = y;
在编译时引发错误
error: no operator "=" matches these operands
operand types are: volatile A = A
如果我删除了volatile,那就可以编译了。反正有没有删除“volatile”(仍然保持volatile的行为)编译?
基本上这是一个CUDA程序,其中'x'是共享内存(所有线程都可以访问和修改其值)。我希望它是“易变的”,以避免编译器优化并重新使用该值而不是访问内存地址。
关于这个问题的更多信息:在开头A只是一个原始类型,例如整数,volatile按预期工作并且不会引起任何问题,现在我希望它是一个自定义类(例如整数128位)。我不确定为什么C ++会在这种情况下抱怨,而不是原始数据类型。
提前致谢。
答案 0 :(得分:7)
假设必须volatile
限定,您必须向A(A& A::operator=(const A&) volatile
)添加易失性赋值运算符。
const_cast<A&>(x) = y
将使其编译,但在技术上会导致未定义的行为,并且肯定会删除volatile
给出的保证。
答案 1 :(得分:2)
“volatile在C ++线程中的用处不大”评论与CUDA特有的问题无关。 CUDA中的warp同步编码需要volatile。
答案 2 :(得分:1)
volatile在C ++线程中没有很多用处(参见Dave Butenhof在http://www.lambdacs.com/cpt/FAQ.html#Q56的解释)。仅仅确保你的程序将核心本地缓存写入的数据刷新到其他程序可以在共享内存中查看更新的点,并且现在几乎每个人的多核都是这样,这是不够的,这是一个严重的问题。我建议您使用正确的线程同步方法,例如如果您的可移植性需要匹配它,或者可能是POSIX互斥锁和条件变量,那么就会失去更多与体系结构相关的技术,如内存屏障或原子操作,这些技术会在内核之间隐式同步内存。
我确信你希望它快速,但快速和不稳定通常不如慢和可靠有用,特别是如果你运送的产品只是在客户的硬件上不稳定。
答案 3 :(得分:1)
声明复制构造函数
volatile A& operator=(volatile A&) volatile;
用nvcc为我工作。请注意,您可能必须仅通过引用传递非基本类型。否则,只要非基本类型通过值传递给非易失性参数,您就需要更多的复制构造函数来将易失性实例转换为非易失性。 它真的归结为建立volatile正确性(很像const-correctness)。