【问题标题】:const_cast VS mutable ? any difference?const_cast VS 可变的?有什么区别吗?
【发布时间】:2012-07-12 18:09:10
【问题描述】:
据我了解,mutable 取消了变量的constness
Class A {
void foo() const {
m_a = 5;
}
mutable int m_a;
};
还有const_cast:
void print (char * str)
{
cout << str << endl;
}
int main () {
const char * c = "this is a line";
print ( const_cast<char *> (c) );
return 0;
}
那么,两者之间有何不同?
谢谢
【问题讨论】:
标签:
c++
constants
mutable
【解决方案1】:
const_cast 不能取消对象的常量。 const_cast 只能从 访问路径 中删除 constness 到一个对象。访问路径是对对象的指针或引用。从访问路径中删除常量对对象本身绝对没有影响。即使您使用const_cast 删除访问路径的常量,也不一定授予您修改对象的权限。能不能做到还是要看对象本身。如果它是 const,则不允许修改它,任何尝试这样做都会导致未定义的行为。
例如,这说明了const_cast 的预期用途
int i = 5; // non-constant object
const int *p = &i; // `p` is a const access path to `i`
// Since we know that `i` is not a const, we can remove constness...
int *q = const_cast<int *>(p);
// ... and legally modify `i`
*q = 10;
// Now `i` is 10
上述合法有效的唯一原因是i 实际上是一个非常量 对象,我们知道这一点。
如果原始对象真的是常量,那么上面的代码会产生未定义的行为:
const int j = 5; // constant object
const int *p = &j; // `p` is a const access path to `j`
int *q = const_cast<int *>(p); // `q` is a non-const access path to `j`
*q = 10; // UNDEFINED BEHAVIOR !!!
C++语言不允许你修改常量对象,const_cast在这里完全无能为力,不管你怎么用。
mutable 是完全不同的东西。 mutable 创建一个可以合法修改的数据文件,即使包含的对象被声明为const。从这个意义上说,mutable 确实允许您修改常量对象的[某些指定部分]。另一方面,const_cast 不能这样做。
【解决方案2】:
不同的是const_cast不能作弊,但mutable是规则的例外。
在第一个 sn-p 上,m_a 是 mutable,因此您不能修改 const 成员函数上的数据成员的规则是一个例外。
在第二个 sn-p 中,const_cast 试图作弊,但实际上不能:虽然 类型 已更改,不允许实际修改:字符串确实是const。尝试修改它会导致程序表现出未定义的行为。
【解决方案3】:
区别在于语义 - i。 e.相同的生成代码,相同的运行时结果(constness 无论如何都是纯粹的编译时构造),但两种构造传达的含义略有不同。
这个想法是你使用mutable 来表示类中的变量,但不构成对象的状态。经典示例是 blob 对象中的当前位置。在 blob 中导航并不算作以重要的方式“修改” blob。通过使用mutable,您是在说“这个变量可能会改变,但对象仍然是相同的”。您是说对于这个特定的类,const-ness 并不意味着“所有变量都被冻结”。
const_cast,另一方面,意味着您违反了现有的 const 正确性并希望摆脱它。可能是因为您正在使用不尊重 const 的第 3 方 API(例如,基于 C 的老式 API)。
【解决方案4】:
简单地说,将成员变量声明为mutable 使其可以从该类的任何常量方法中写入访问,而无需任何其他特殊语法。另一方面,const_cast 必须在您想要对其他常量变量进行写访问时执行,并且该变量甚至不必是类成员。
除非您想明确允许对成员变量进行写访问,否则最好在每次违反 const 正确性的情况下使用 const_cast,如果只是为了明确说明您的意图。
附带说明,const_cast 也可用于添加或删除volatile 修饰符。