Типизированные константы
Нет разницы между 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;
Ссылки
Стоит помнить, что ссылка сама по себе является неизменяемой:
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_;
};