объясните по 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 шт):

Автор решения: HolyBlackCat

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);

}
→ Ссылка
Автор решения: Fat-Zer

Присваивать объекту, который был определён как 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 !!
→ Ссылка