Неопределенное поведение при преобразовании const_cast
by
Несмотря на то, что C++ предоставляет возможность принудительного изменения типа переменной или "снятия" модификатора const, использование в программах этих методов не рекомендуется и считается плохим тоном. Расмотрим в качестве иллюстрации функцию, которая получает ссылку на константное целое, но изменяет его значение.
void set_value(const int &var, int value) {
int &non_const_var = const_cast<int &>(var);
non_const_var = value;
}
В данном примере ссылка на константный объект var преобразуется
к ссылке на изменяемый объект. Поскольку переменная non_const_var
имеет тип int &
, то она ссылается на существующий объект
типа int. Изменение значения non_const_var
изменяет
и объект var, так как var и non_const_var являются двумя
названиями одного объекта в памяти. В теории.
Поведение данной функции зависит от того, каким образом она была вызвана. В приведенном ниже прмере будет выведено вполне ожидаемое сообщение "k = 1".
#include <iostream>
int main() {
int k = 0;
set_value(k, 1);
std::cout << "k = " << k << std::endl; // k = 1
}
Если же переменная k будет объявлена константной, то поведение программы неопределено.
#include <iostream>
int main() {
const int k = 0;
set_value(k, 1);
std::cout << "k = " << k << std::endl; // k = 0 !!!
}
Вероятнее всего, значение переменной k не изменится.
Разница между этими примерами состоит в том, что в последнем случае компилятор может, поскольку переменная k объявлена неизменяемой, либо разместить ее в недоступной для изменения области памяти, либо вообще заменить все вхождения k константой 0. В любом случае модификация значения k будет некорректной. Заметим, что функция set_value не может различить эти ситуации, а потому является небезопасной.