Что означает ключевое слово const в C++?

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

Ответ

Ключевое слово const в C++ указывает на неизменяемость (константность) объекта или выражения после его инициализации. Это обещание компилятору и другим программистам, что значение не будет изменено, что повышает безопасность, читаемость и позволяет проводить некоторые оптимизации. const является частью системы типов и проверяется на этапе компиляции.

Основные контексты использования:

  1. Константные переменные и объекты:

    const int MAX_BUFFER_SIZE = 1024;
    const std::string GREETING = "Hello";
    // MAX_BUFFER_SIZE = 2048; // Ошибка компиляции: присваивание константе
  2. Указатели и const: Здесь важно различать указатель на константу и константный указатель.

    int value = 10;
    int other = 20;
    
    // 1. Указатель на константное целое (данные нельзя менять через этот указатель)
    const int* ptr_to_const = &value;
    // *ptr_to_const = 30; // Ошибка: данные константны
    ptr_to_const = &other; // OK: сам указатель можно перенаправить
    
    // 2. Константный указатель (указатель нельзя перенаправить)
    int* const const_ptr = &value;
    *const_ptr = 30; // OK: данные можно менять
    // const_ptr = &other; // Ошибка: указатель константен
    
    // 3. Константный указатель на константные данные
    const int* const const_ptr_to_const = &value;
    // *const_ptr_to_const = 30; // Ошибка
    // const_ptr_to_const = &other; // Ошибка
  3. Константные методы класса: Метод, объявленный с const в конце сигнатуры, гарантирует, что он не будет изменять нестатические поля объекта (за исключением полей, объявленных как mutable). Константные объекты могут вызывать только константные методы.

    class DataContainer {
        std::vector<int> data;
        mutable int accessCounter = 0; // Можно менять даже в const-методах
    public:
        // Не-константный метод: может изменять объект
        void add(int value) { data.push_back(value); }
    
        // Константный метод: не может изменять объект (кроме mutable полей)
        int getSize() const {
            ++accessCounter; // Разрешено, так как accessCounter - mutable
            return data.size();
        }
        // int getLast() { return data.back(); } // Нельзя вызвать для const DataContainer
        int getLast() const { return data.back(); } // Можно вызвать для const DataContainer
    };
    
    int main() {
        DataContainer dc;
        dc.add(5);
        std::cout << dc.getSize(); // OK
    
        const DataContainer& const_ref = dc;
        // const_ref.add(10); // Ошибка: add() не является const-методом
        std::cout << const_ref.getSize(); // OK: getSize() - const
    }
  4. Константные параметры функций и возвращаемые значения: Гарантируют, что функция не изменит переданный аргумент или что возвращаемое значение нельзя изменить.

    void printVector(const std::vector<int>& vec) { // Безопасная передача по ссылке
        for (int val : vec) std::cout << val << ' ';
        // vec.push_back(10); // Ошибка компиляции
    }
    
    const int* find(const int* arr, int size, int target) {
        // Возвращаем указатель на константу, чтобы caller не мог изменить найденный элемент
        for (int i = 0; i < size; ++i) if (arr[i] == target) return &arr[i];
        return nullptr;
    }

    Использование const — это хорошая практика, которая делает контракты функций явными и предотвращает множество ошибок.