Как присвоить значение константному объекту?

«Как присвоить значение константному объекту?» — вопрос из категории C++ Core, который задают на 25% собеседований C/C++ Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Прямое присваивание значения константному объекту в C++ запрещено и нарушает гарантии языка. Попытки обойти это с помощью const_cast или обращения через указатель приводят к неопределённому поведению (UB), если исходный объект был создан как константный.

const int x = 10;
// const_cast<int&>(x) = 20; // Неопределённое поведение!
// int* ptr = (int*)&x; *ptr = 20; // Неопределённое поведение!

Правильные подходы:

  1. Использование mutable членов данных: Поле, объявленное как mutable, может быть изменено даже внутри const-методов.
class Logger {
    mutable std::vector<std::string> log_cache; // Кэш логов может изменяться
public:
    void addToLog(const std::string& entry) const { // Константный метод
        log_cache.push_back(entry); // Разрешено, так как log_cache - mutable
    }
};
  1. Создание копии с изменениями: Если нужно модифицировать данные, создайте неконстантную копию объекта.
const std::string original = "Hello";
std::string modified = original; // Копирование
modified += " World!";           // Модификация копии
  1. Использование указателя на изменяемую память: Если объект физически находится в изменяемой памяти (например, в сыром массиве), можно использовать const_cast, но только если уверены, что объект не был изначально константным.
int raw_array[10] = {};
const int* const_ptr = &raw_array[0]; // Указатель на константу
int* mutable_ptr = const_cast<int*>(const_ptr); // Снимаем const
*mutable_ptr = 42; // Допустимо, так как raw_array - не константный

Основной принцип: Если возникает потребность изменить константный объект, это сигнал о проблеме в дизайне программы. Следует пересмотреть архитектуру, чтобы либо не требовать изменения (mutable для логически неконстантных операций), либо работать с неконстантными копиями.