const_cast VS изменчивый? какая разница?

Из моего понимания, 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 ответа

Решение

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 и надеетесь сойти с рук. Возможно, потому что вы работаете с сторонним API, который не уважает const (например, старая школа на основе C).

Проще говоря, объявив переменную-член как mutable делает его доступным для записи из любого константного метода этого класса без какого-либо специального синтаксиса. const_cast с другой стороны, это необходимо выполнять всякий раз, когда вы хотите получить доступ на запись к другой постоянной переменной, и эта переменная даже не должна быть членом класса.

Если вы не хотите явно разрешить доступ на запись к переменной-члену, используя const_cast в каждом случае нарушения const правильность предпочтительна, если только четко заявить о своих намерениях.

С другой стороны, const_cast также может использоваться для добавления или удаления volatile модификатор.

Другие вопросы по тегам