@著作权归作者所有:来自CSDN博客作者大胡子的艾娃的原创作品,如需转载,请注明出处https://blog.csdn.net/qq_43148810,否则将追究法律责任。 如有错误的地方欢迎指正,谢谢!
一、volatile介绍
volatile限定符和const很相似,起到对类型额外的修饰作用,并且和可以构成重载。
二、对类型额外的修饰作用
1、当对象的值可能在程序的控制和检测之外被改变时,应该对该对象声明为volatile。 2、声明volatile后对象的创建不发生reorder(1、先分配内存,再调用构造去初始化这块内存,最后将m_instance指针指向这块内存;2、先分配内存,再将m_instance指针指向这这段内存,最后调用构造去初始化这块内存。reorder就是是指1和2两种不定的情况。) 3、不会在两个操作之间把volatile变量缓存在寄存器中,都会直接从变量地址中读取数据,不会出现副本(寄存器)和实际内存值不一致的现象。 4、一般volatile对debug版无作用,debug一般不做优化。 5、非volatile的引用不能绑定到volatile对象 6、如果一个类希望拷贝、移动和赋值其volatile声明的对象功能,则必须自定义该版本的拷贝、移动和赋值函数。
三、volatile使用场景:
1、中断服务程序中修改的供其它程序检测的变量需要加volatile; 2、多任务环境下各任务间共享的标志应该加volatile; 3、存储器映射的硬件寄存器通常也要加volatile说明,因为每次对它的读写都可能由不同意义; 另外,以上这几种情况经常还要同时考虑数据的完整性(相互关联的几个标志读了一半被打断了重写),在1中可以通过关中断来实现,2中可以禁止任务调度,3中则只能依靠硬件的良好设计了。
四、构成重载
#include <iostream>
class My
{
public:
void show()
{
std::cout << "test_and_set\n";
}
void show() volatile
{
std::cout << "volatile\n";
}
};
int main()
{
My my1;
volatile My my2;
my1.show();
my2.show();
return 0;
}
1、test_and_set和clear接口都重载了volatile 接口 2、同const一致,但互不影响。重载调用关系也和const一致,volatile对象只能调用volatile接口,非volatile优先重载非volatile接口。
五、标准库原子量std::atomic_flag的实现分析
#define ATOMIC_FLAG_INIT {0}
typedef struct atomic_flag
{
bool test_and_set(memory_order _Order = memory_order_seq_cst) volatile noexcept;
bool test_and_set(memory_order _Order = memory_order_seq_cst) noexcept;
void clear(memory_order _Order = memory_order_seq_cst) volatile noexcept;
void clear(memory_order _Order = memory_order_seq_cst) noexcept;
_Atomic_flag_t _My_flag;
atomic_flag() noexcept = default;
atomic_flag(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) = delete;
atomic_flag& operator=(const atomic_flag&) volatile = delete;
} atomic_flag;
inline bool atomic_flag::test_and_set(memory_order _Order) volatile noexcept
{
return (_Atomic_flag_test_and_set(&_My_flag, _Order));
}
inline bool atomic_flag::test_and_set(memory_order _Order) noexcept
{
return (_Atomic_flag_test_and_set(&_My_flag, _Order));
}
inline void atomic_flag::clear(memory_order _Order) volatile noexcept
{
_Atomic_flag_clear(&_My_flag, _Order);
}
inline void atomic_flag::clear(memory_order _Order) noexcept
{
_Atomic_flag_clear(&_My_flag, _Order);
}
inline bool atomic_flag_test_and_set(volatile atomic_flag *_Flag) noexcept
{
return (_Atomic_flag_test_and_set(&_Flag->_My_flag, memory_order_seq_cst));
}
inline bool atomic_flag_test_and_set(atomic_flag *_Flag) noexcept
{
return (_Atomic_flag_test_and_set(&_Flag->_My_flag, memory_order_seq_cst));
}
inline bool atomic_flag_test_and_set_explicit(volatile atomic_flag *_Flag, memory_order _Order) noexcept
{
return (_Atomic_flag_test_and_set(&_Flag->_My_flag, _Order));
}
inline bool atomic_flag_test_and_set_explicit(atomic_flag *_Flag, memory_order _Order) noexcept
{
return (_Atomic_flag_test_and_set(&_Flag->_My_flag, _Order));
}
inline void atomic_flag_clear(volatile atomic_flag *_Flag) noexcept
{
_Atomic_flag_clear(&_Flag->_My_flag, memory_order_seq_cst);
}
inline void atomic_flag_clear(atomic_flag *_Flag) noexcept
{
_Atomic_flag_clear(&_Flag->_My_flag, memory_order_seq_cst);
}
inline void atomic_flag_clear_explicit(volatile atomic_flag *_Flag, memory_order _Order) noexcept
{
_Atomic_flag_clear(&_Flag->_My_flag, _Order);
}
inline void atomic_flag_clear_explicit(atomic_flag *_Flag, memory_order _Order) noexcept
{
_Atomic_flag_clear(&_Flag->_My_flag, _Order);
}
1、test_and_set和clear均实现volatile和非volatile两个版本。 2、类atomic_flag用于多任务环境下各任务间共享的标志
更多内容请关注个人博客:https://blog.csdn.net/qq_43148810
|