mutable
mutable 意思是“易变的”。
const
类型对象的mutable
域可以修改, 如果通过const
指针或引用访问对象,mutable
域也可以修改。简而言之,使用mutable
关键字将覆盖任何封闭的const
语句,编译器会因为此关键字不会将对象存储于只读内存中。
(A mutable field can be changed even in an object accessed through a const pointer or reference, or in a const object, so the compiler knows not to stash it in R/O memory. )
mutable
与const
进行交互。 如果你有一个const
指针,你通常不能改变成员。 mutable
为该规则提供了一个例外。
volatile
volatile意思也是“易变的”。
关键字volatile
依赖于实现,声明变量时使用,将阻止编译器优化这些变量。如果变量的值会出其不意地被修改(例如中断, 或者一些内核级驱动),而编译器根本不知道, 这样的修改会与编译器可能会执行的优化行为相冲突,volatile
的作用就是告诉编译器不要进行优化。例如:x = 1; x = 0;
如果x
声明为volatile
, 那么即使编译器将执行两条写操作(在硬件级别可能非常重要), 如果没有volatile
, 编译器有可能不会执行写1
操作,毕竟 1
从来没用到。声明为 volatile
变量的修改不受程序控制,编译器不得将这些变量内容存在寄存器中,必须每次读或写内存地址。
比如说你在控制LED灯的状态, 写0
设为OFF,写1
设为ON。如果想用LED显示一些错误状态,可是编译器自行决定优化所有的写操作,只保留最后一条,毕竟前面的若干值全都没有使用,那么LED不会闪烁,期望的行为不会实现。
测试 mutable
class Transformation
{
private:
vec3 translation;
vec3 scale;
vec4 rotation;
mutable mat4 transformation;
mutable bool changed;
public:
Node()
{
[...]
changed = false;
}
void set_translation(vec3 _translation)
{
translation = _translation;
changed = true;
}
void set_scale(...) ...
mat4 get_transformation() const
{
if(changed)
{
// transformation and changed need to be mutable here
// This take a long time...
transformation = f(translation, scale, rotation);
changed = false;
}
return transformation;
}
};
void apply_tranformation(const Transformation* transfo)
{
apply(transfo->get_transformation());
}
我自己写的测试代码:
class TestMutable {
private:
mutable int count;
public:
TestMutable(int n) : count(n) {}
void printValue() const
{
// 如果前面没有加 mutable, 这一行编译会显示:
// 由于正在通过常量对象访问count, 因此无法对其修改。
count++;
cout << count << endl;
}
};
int _tmain(int argc, char* argv[])
{
const TestMutable obj(0);
obj.printValue();
system("pause");
return 0;
}
编译通过,输出1.
来自于stackoverflow的答案。
[1] https://stackoverflow.com/questions/2444695/volatile-vs-mutable-in-c/2444705
[2] https://stackoverflow.com/questions/4554031/when-have-you-used-c-mutable-keyword