const_cast VS可变?任何差异
const_cast VS mutable ? any difference?
根据我的理解,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;
}
那么,是什么改变了一个和另一个?
感谢
const_cast
无法取消对象的常量。const_cast
只能从对象的访问路径中移除常量。访问路径是指向对象的指针或引用。从访问路径中删除常量对对象本身绝对没有影响。即使使用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
不能做那样的事情。
区别在于const_cast
不能作弊,但mutable
是规则的例外。
在第一个代码段中,m_a
是mutable
,因此是不能修改const
成员函数上的数据成员的规则的例外。
在第二个片段中,const_cast
试图作弊,但确实不能:虽然类型已经更改,但不允许实际修改:字符串确实是const
。试图修改它会导致程序表现出未定义的行为。
不同之处在于语义,即生成的代码相同,运行时结果相同(无论如何,const
ness是一个纯粹的编译时构造),但这两个构造传达的含义略有不同。
其思想是对类中的变量使用mutable
,但不构成对象的状态。经典示例是blob对象中的当前位置。在blob中导航并不算作以重要的方式"修改"blob。使用mutable
,表示"此变量可能会更改,但对象仍然相同"。您指出,对于这个特定的类,const
-ness并不意味着"所有变量都被冻结"。
另一方面,const_cast
意味着你违反了现有的const正确性,并希望逃脱惩罚。可能是因为你使用的是不尊重const
的第三方API(例如,基于C的老式API)。
简单地说,将成员变量声明为mutable
使其可以从该类的任何常量方法进行写访问,而无需任何其他特殊语法。另一方面,每当您想要对一个常量变量进行写访问时,就必须执行const_cast
,而且该变量甚至不必是类成员。
除非您想明确允许对成员变量进行写访问,否则在所有违反常量正确性的情况下,如果只是为了清楚地说明您的意图,则最好使用const_cast
。
附带说明一下,const_cast也可以用于添加或删除volatile
修饰符。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- OpenMP阵列性能较差
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 具有重复类型的C++可变模板
- 如何在不产生任何垃圾的情况下获得C中的像素
- 高效的可变参数等于任何函数
- 谷神星求解器:残差函子使用的可变对象是否良好实践?还有什么其他选择
- 声明类型没有任何可变类型
- 接受对任何类型的可变引用的 Lambda
- 任何返回类型的可变参数函数包装器
- 为什么我的可变参数宏不能正确接受任何参数?
- 如何从可变参数构造函数参数构造任何对象?
- 这个错误意味着什么:在任何函数之外声明的可变大小类型
- 是否有任何理由使模板模板参数不可变
- const_cast VS可变?任何差异
- 是否有任何选项可以推迟对可变参数模板中函数调用的评估
- 具有可变数量参数但没有任何显式参数的函数
- C++与任何类型的参数匹配的可变参数模板模板参数
- Ellipsis作为任何可变模板之外的构造函数参数
- 解包可变宏的任何技巧