Перейти к содержимому
Теория · Приведения и псевдонимы · урок 3 из 7

const_cast и reinterpret_cast

Представьте вещь в музейной витрине с табличкой «только смотреть». Смотреть на неё может любой, а трогать нельзя никому. const у переменной — такая табличка: значение можно читать, но не менять.

static_cast меняет тип значения, но снять const с указателя он не может:

C++
int main() {
    const int limit = 10;
    int* p = static_cast<int*>(&limit);  // ✗
    return *p;
}
TEXT
error: static_cast from 'const int *' to 'int *' is not allowed

Снимать const и переинтерпретировать указатели умеют другие именованные приведения. У каждого из них одна задача.

const_cast

const_cast снимает const с указателя или ссылки и больше ничего не меняет: const_cast<int*>(&limit) — это int* на тот же limit. Тип значения он не меняет, поэтому const_cast<int>(2.5) не скомпилируется. Его применяют, когда функция принимает int*, но значение только читает:

C++
#include <iostream>

void print_value(int* p) {
    std::cout << *p << '\n';
}

int main() {
    const int limit = 10;
    print_value(const_cast<int*>(&limit));  // 10
}

Без const_cast адрес const-переменной в такую функцию не передать: const int* в int* компилятор сам не превращает.

Здесь аналогия с витриной заканчивается важным правилом. const_cast снимает табличку только с вашего указателя, а сама вещь остаётся музейной. Если переменную объявили с const, менять её нельзя и после приведения.

reinterpret_cast и void*

С указателями reinterpret_cast даёт указатель на другой тип с тем же адресом. Байты в памяти остаются прежними: меняется только тип, через который программа их читает. Прочитать float через int* — неопределённое поведение, поэтому начинающему это приведение почти не нужно. Числа reinterpret_cast не преобразует: reinterpret_cast<int>(2.5) не скомпилируется.

Некоторые указатели меняют тип и без приведения. int* неявно превращается в void*, указатель на значение неизвестного типа. Обратно в int* его возвращает static_cast<int*>.

Четвёртое именованное приведение, dynamic_cast, работает только с указателями и ссылками на составные типы вроде struct, а с числами — нет.

Частая ошибка

Через const_cast записывают в переменную, объявленную с const:

C++
int main() {
    const int limit = 10;
    int* p = const_cast<int*>(&limit);
    *p = 20;  // ✗
    return limit;
}

Компилятор собирает программу без ошибок и предупреждений. Но limit объявлена с const, и запись в неё через p — неопределённое поведение: стандарт не говорит, что вернёт main. Писать через const_cast можно только в переменную, объявленную без const. Если значение должно меняться, уберите const из объявления.

Главное

  • const_cast снимает const с указателя или ссылки и не меняет тип значения.
  • Записывать через const_cast в переменную, объявленную с const, — неопределённое поведение.
  • reinterpret_cast читает те же байты как другой тип и числа не преобразует.
  • int* неявно превращается в void*, а обратно его возвращает static_cast<int*>.

Подпишись, чтобы пройти курс

Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.

Войти другим способом