const_cast VS可变吗?有何不同?

时间:2012-07-12 18:09:10

标签: c++ const mutable

据我了解,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;
}

那么,是什么改变了另一个?

谢谢

4 个答案:

答案 0 :(得分:17)

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不能做那样的事情。

答案 1 :(得分:4)

区别在于const_cast不能作弊,但mutable是规则的例外。

在第一个代码段m_a上是mutable,因此您无法修改const成员函数上的数据成员的规则例外。

在第二个代码段上,const_cast尝试作弊,但实际上不能:当类型发生更改时,不允许进行实际修改:字符串是真正的const。试图修改它会导致程序出现未定义的行为。

答案 2 :(得分:1)

区别在于语义 - 我。即相同的生成代码,相同的运行时结果(const ness无论如何都是一个纯粹的编译时构造),但这两个结构传达的意思略有不同。

这个想法是你使用mutable作为类中的变量,但不构成对象的状态。典型的例子是blob对象中的当前位置。在blob中导航并不算作&#34;修改&#34; blob以一种重要的方式。通过使用mutable,您可以说&#34;此变量可能会更改,但对象仍然相同&#34;。您已经声明,对于这个特定的类,const - 并不意味着&#34;所有变量都被冻结&#34;。

另一方面,

const_cast意味着您违反现有的常规正确性并希望能够逃脱它。可能是因为您正在使用不尊重const的第三方API(例如,基于C的老式学校)。

答案 3 :(得分:0)

简单地说,将成员变量声明为mutable使得它可以从该类的任何常量方法中进行写操作,而无需任何其他特殊语法。另一方面,只要您希望对其他常量变量进行写访问,就必须执行const_cast,并且该变量甚至不必是类成员。

除非你想明确允许对成员变量进行写访问,否则在每个违反const正确性的情况下使用const_cast是首选,只要明确说明你的意图。

另外,const_cast还可用于添加或删除volatile修饰符。

相关问题