Skip to the content.

Типизированные константы

Нет разницы между const <тип> и <тип> const:

double const pi = 3.14;
const int days[3] = {31, 28, 31};

Указатели

Указатель на константу (изменить значение на которое он указывает нельзя):

const int *p;
int const *p;

Константный указатель (изменить адрес на который он указывает нельзя):

int * const p;

Константный указтель на константу:

int const * const p;

easy pointer

Ссылки

Стоит помнить, что ссылка сама по себе является неизменяемой:

int & const l; // ERROR

Ссылка на константу:

const int & l;
int const & l;

Стоит отметить, что ссылка на константу позволяет инициализацию при помощи rvalue (обычная ссылка принимает только lvalue):

const int & l = 5;

Методы классов

Такие методы не могут изменять поля экземпляра (this - указывает теперь на const):

struct IntArray
{
  void size() const
  {
      this->age++; //ERROR
  };  
  
  void resize()
  {
      this->age++;
  };  
  
  int age;
};

Также внутри константных методов можно вызывать только константные методы.

Слово const нужно указывать и при объявлении и при опеределении метода. Это позволяет создавать две версии одного и того же метода (с const и без).

У константных экземпляров можно вызвать только константные методы:

const IntArray a;
a.size();
a.resize(); // ERROR

Синтаксическая константность - константные методы не могут менять поля экземпляра.

Логическая константность - нельзя изменять те данные, которые обеспечивают состояние объекта.

Синтаксическая и логическая константности могут не совпадать:

struct IntArray
{
    void foo() const
    {
        // нарушение логической константности
        data_[10] = 1;
    }
    
    size_t = size_;
    int * data_;
};

Мы не можем изменять size_ и data_, но данные на которые указывает data_ можем.

Ключевое слово mutable позволяет определять поля, которые можно изменять внутри константных методов:

struct IntArray
{
    void foo() const
    {
        ++counter_;
    }
    
    size_t = size_;
    int * data_;
    mutable size_t counter_;
};