C++ 常量对易变?有什么区别吗?

C++ 常量对易变?有什么区别吗?,c++,constants,mutable,C++,Constants,Mutable,根据我的理解,mutable取消变量的constanness Class A { void foo() const { m_a = 5; } mutable int m_a; }; 但也包括const\u cast: void print (char * str) { cout << str << endl; } int main () { const char * c = "this is a line"; print ( const_cast&

根据我的理解,
mutable
取消变量的
constanness

Class A {
  void foo() const {
  m_a = 5;
}
mutable int m_a;
};
但也包括
const\u cast

void print (char * str)
{
  cout << str << endl;
}

int main () {
  const char * c = "this is a line";
  print ( const_cast<char *> (c) );
  return 0;
}
void打印(char*str)
{

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

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


const\u cast
,另一方面,意味着您违反了现有的const正确性,并希望侥幸逃脱。可能是因为您使用的第三方API不尊重
const
(例如,基于C的旧式API).

区别在于
const\u cast
不能作弊,但
mutable
是规则的例外

在第一个代码段中,m_a
可变的
,因此这是一个例外,即不能修改
常量
成员函数上的数据成员


在第二个代码段中,
const\u cast
试图欺骗,但实际上无法欺骗:虽然类型已更改,但不允许实际修改:字符串确实是
const
。试图修改它将导致程序显示未定义的行为。

const\u cast
无法取消对象的常量。
const\cast
只能从对象的访问路径中删除常量。访问路径是指向对象的指针或引用。从访问路径中删除常量对对象本身绝对没有影响。即使使用
const\u cast
删除访问路径的常量,也不一定能获得per修改对象的任务。是否可以修改仍然取决于对象本身。如果它是常量,则不允许修改它,任何尝试都将导致未定义的行为

例如,这说明了
const\u 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
C++语言不允许您修改常量对象,
const_cast
在这里完全无能为力,无论您如何使用它


mutable
是一个完全不同的东西。
mutable
创建了一个可以合法修改的数据字段,即使包含的对象被声明为
const
。从这个意义上讲,
mutable
允许您修改[数据的某些指定部分]常量对象。
const_cast
,另一方面,不能做任何类似的事情。

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

除非您希望明确允许对成员变量进行写访问,否则最好在每次违反常量正确性的情况下使用
const\u cast
,如果只是为了清楚地说明您的意图

另一方面,const_cast还可用于添加或删除
volatile
修饰符

  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 !!!