Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C+中的易变与易变+;_C++_Volatile_Mutable - Fatal编程技术网

C++ 在C+中的易变与易变+;

C++ 在C+中的易变与易变+;,c++,volatile,mutable,C++,Volatile,Mutable,我有一个关于易变和易变的区别的问题。我注意到这两者都意味着它可以改变。还有什么?它们是一样的吗?有什么区别?它们在哪里适用?为什么提出这两个想法?如何以不同的方式使用它们 非常感谢 它们绝对不是一回事。可变表与常量交互。如果您有常量指针,通常无法更改成员。Mutable提供了该规则的一个例外 另一方面,Volatile与程序所做的更改完全无关。这意味着内存可能会因编译器无法控制的原因而更改,因此编译器每次都必须读取或写入内存地址,并且不能将内容缓存在寄存器中。mutable:mutable关键字

我有一个关于易变和易变的区别的问题。我注意到这两者都意味着它可以改变。还有什么?它们是一样的吗?有什么区别?它们在哪里适用?为什么提出这两个想法?如何以不同的方式使用它们


非常感谢

它们绝对不是一回事。可变表与常量交互。如果您有常量指针,通常无法更改成员。Mutable提供了该规则的一个例外


另一方面,Volatile与程序所做的更改完全无关。这意味着内存可能会因编译器无法控制的原因而更改,因此编译器每次都必须读取或写入内存地址,并且不能将内容缓存在寄存器中。

mutable
:mutable关键字覆盖任何包含的const语句。可以修改常量对象的可变成员

volatile
:volatile关键字是一个依赖于实现的修饰符,在声明变量时使用,它阻止编译器优化这些变量。Volatile应与值可能以意外方式(即通过中断)更改的变量一起使用,这可能与编译器可能执行的优化冲突


即使在通过
常量
指针或引用访问的对象中,或者在
常量
对象中,
可变
字段也可以更改,因此编译器知道不要将其存储在R/O内存中。
volatile
位置可以通过编译器不知道的代码(例如某些内核级驱动程序)进行更改,因此编译器知道不优化该值的寄存器分配,例如,在无效假设下,该值自上次加载到该寄存器后“不可能已更改”。为编译器提供了非常不同类型的信息,以停止非常不同类型的无效优化。

标记为
可变的变量允许在声明为
常量的方法中对其进行修改


标记为
volatile
的变量告诉编译器,每次代码告诉它时,它都必须读/写该变量(即,它不能优化对该变量的访问)。

一种粗略但有效的方法是:

  • 编译器知道可变对象何时更改
  • 编译器无法知道易失性对象何时更改

我想补充一点,volatile在处理多线程应用程序时也非常有用,即,您拥有主线程(main()所在的位置),并且生成一个工作线程,当变量“app_running”为真时,该线程将继续旋转。main()控制“app_running”是true还是false,因此如果不将volatile属性添加到“app_running”的声明中,如果编译器优化对次线程运行的代码中“app_running”的访问,main()可能会将“app_running”更改为false,但次线程将继续运行,因为该值已被缓存。我在Linux和VisualC++上看到了使用gcc的相同行为。“app_running”声明中的“volatile”属性解决了这个问题。因此,在这种情况下,更改这些变量的值时不涉及硬件中断或内核。

volatile
对象也可以由根本不涉及CPU的进程更改。例如,通信外围设备中接收到的字节寄存器可以在接收到字节时自行递增(这甚至可以触发中断)。另一个例子是外设中的挂起中断标志寄存器。此外,
volatile
不仅意味着对象可以在编译器不知情的情况下更改,还意味着编译器无法消除对对象的写入,即使这些写入看起来毫无用处。例如:
x=1;x=0
如果
x
是易失性的,编译器必须发出两个写操作(这在硬件级别可能很重要)。但是,对于非易失性对象,编译器可以选择不编写
1
,因为它从未使用过。对象可以标记为
const
volatile
!您不能更改对象,但可以在背后更改。@析构函数:通常的情况是写入硬件设备寄存器。@析构函数假设您正在控制LED的状态。写入0将关闭它,写入1将打开它。如果我需要闪烁LED来传达一些错误状态,但编译器决定优化除最后一个之外的所有写入,因为没有使用任何值,那么LED从不闪烁,我想要的行为也没有实现。这样:
volatile
bytes\u received,
mutable
reference\u count.No!这是一个常见的误解。C++11和C11为此引入了原子。您说过,
Volatile应与值可能以意外方式变化的变量一起使用
我们是否更愿意将其用于random?@AsifMushtaq not值。方式。可变影响您编写的代码所具有的权限。因此,您可以通过const ptr或const引用访问变量。如果不是你的代码改变了它怎么办?编译器无法检查ptr或引用类型的内容?这是不稳定的。而且volatile还强制缓存写回主内存。因此,这在多线程代码中经常使用。:)“另一方面,Volatile与程序所做的更改完全无关……”-hmmm,让一个成员Volatile,看看编译过程中有什么中断。尝试在事实之后添加volatile与尝试在事实之后添加const非常相似。。。痛苦。@jww:这与程序的写入完全无关。您可以获取类型为
T
的对象的地址,并将其存储到
常量T*
中并从中读取。如果将该对象设置为易变的,则