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
модификатор.