9

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

4 回答 4

20

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,另一方面,不能做这样的事情。

于 2012-07-12T18:17:14.680 回答
4

不同的是const_cast不能作弊,而是mutable规则的例外。

在第一个片段m_a上是mutable,因此您不能修改const成员函数上的数据成员的规则是一个例外。

在第二个片段上,const_cast试图作弊,但实际上不能:虽然类型已更改,但不允许实际修改:字符串是 true const。尝试修改它会导致程序表现出未定义的行为。

于 2012-07-12T18:16:26.843 回答
3

区别在于语义——即相同的生成代码,相同的运行时结果(constness 无论如何都是纯粹的编译时构造),但两种构造传达的含义略有不同。

这个想法是您使用mutable类中的变量,但不构成对象的状态。经典示例是 blob 对象中的当前位置。在 blob 中导航并不算作以重要的方式“修改” blob。通过使用mutable,您是在说“这个变量可能会改变,但对象仍然是相同的”。您是说对于这个特定的类,const-ness 并不意味着“所有变量都被冻结”。

const_cast,另一方面,意味着您违反了现有的 const 正确性并希望摆脱它。可能是因为您正在使用不尊重的第 3 方 API const(例如基于 C 的老式 API)。

于 2012-07-12T18:15:58.293 回答
0

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

除非您想明确允许对成员变量的写访问,否则const_cast最好在每种违反 const 正确性的情况下使用,如果只是为了清楚地说明您的意图。

附带说明一下, const_cast 也可用于添加或删除volatile修饰符。

于 2012-07-12T18:28:26.150 回答