объясните по const_cast
Скажите вот читаю про const_cast. написано const_cast позволяет лишить статуса const или volatile переменную . Но такое ощущение , что не совсем ведь так буквально: потому что рассматривать её как полноценную переменную я не могу :
const int i = 0;
const_cast<int*>(&i);
i = 555;
но могу вот так :
const int i = 0;
int* j = const_cast<int*>(&i);
*j = 555;
то есть , если объявлено const int i = 0;, то после const_cast i можно менять только при помощи указателя ?
Ответы (2 шт):
const_cast саму переменную не меняет. Он просто возвращает указатель, который вы ему передали, с измененным типом: вы передали ему const int *, а на выходе получили int *, указывающий на ту же переменную.
Конечно, если не использовать то, что этот каст возвращает, тогда он вообще ничего не делает.
Ваш второй пример, хотя и компилируется, тоже некорректен (вызывает неопределенное поведение), потому что вы модифицируете константную переменную.
const_cast можно использовать только чтобы модифицировать неконстантную переменную, если у вас почему-то есть только указатель-на-const (или константная ссылка) на нее.
Пример:
void f(const int *ptr)
{
// *ptr = 42; // Ошибка, потому что в указателе `const`.
*const_cast<int *>(ptr) = 42; // Ок.
}
int main()
{
int foo = 0; // Ок.
// const int foo = 0; // Не ок, неопределенное поведение из-за изменения константы.
f(&foo);
}
Присваивать объекту, который был определён как const — это в любом случае UB (undefined behavior). const_cast ни коим образом не снимает константность с самого объекта, он только «возвращает» переданное ему значение с нужным типом (это выражение также может быть «присваиваемым» (l-value)).
На практике const_cast используется довольно редко. Обычно это относительно грязный хак, чтобы передать константный объект в функцию, которая заведомо его не меняет (но принимает неконстантную ссылку/указатель) или, наоборот, изменить объект заведомо созданные как неконстантный, но переданный по константной ссылке/указателю. В тривиальном варианте это выглядит как-то так:
void foo (const int &i) {
const_cast<int &>(i) = 2;
}
void bar (int *i) {
std::cout << *i;
}
// ...
int i=0;
const int ci=2;
foo(i);
bar(const_cast<int*>(&ci));
По непосредственному вопросу: с точки зрения синтаксиса можно привести константную переменную к неконстантной ссылке (само собой так делать не стоит):
const int i = 0;
const_cast<int&>(i) = 2; // !! UB !!