Ключевое слово const служит для создания неизменяемой (константной) переменной, указателя или функции и т.д.
#include <iostream>
int main() {
int const a = 1; // Теперь переменную нельзя изменить, она всегда равна 1. Нельзя a = 3;
const int b = 2; // То же самое. const может быть до и после типа. Нельзя b = 5;
int c = 5; // Обычная переменная
const int* pa = &a; // Можно pa = &b но нельзя *pa = b
int* const pc = &c; // Можно *pb = b но нельзя pb = &b
const int* const p = &a; // Нельзя *p = b и нельзя p = &b
std::cout << "a = " << a << "\nb = " << b << "\nc = " << c << "\npa = " << pa << ", *pa = " << *pa << "\npc = " << pc << ", *pc = " << *pc << std::endl;
}
/* Вывод программы
a = 1
b = 2
c = 5
pa = 0x61fe6c, *pa = 1
pc = 0x61fe68, *pc = 5
*/
Существует мнемоническое правило, позволяющее легко запомнить, к чему относится const. Надо провести черту через "*", если const слева, то оно относится к значению данных; если справа — к значению указателя.
Константные функции не могут изменять объект для которого вызываются.
Константные объекты могут вызывать только константные функции.
#include <iostream>
class A {
int x = 10;
public:
A(int val){ // Конструктор
x = val; // Можно менять x не из константных функций
}
void print_con(int a) const { // Константная функция
std::cout << "a = " << a << ", x = " << x << std::endl;
a = x; // OK
// x = a; // Ошибка. изменение объекта константной функцией
}
void print(){
std::cout << "x = " << x << std::endl;
}
};
int main() {
A a(20); // Создаем объект
a.print(); /// x = 20
const A b(30); // Создаем константный объект
// b.print(); // Ошибка. Нельзя вызывать неконстантную функцию из константного объекта
b.print_con(40); /// a = 40, x = 30
}
1) Аргументы передаваемые по ссылке или указатели рекомендуется указывать как константные, если их не изменяют внутри функции, это хорошо описывает назначение кода и не дает случайно изменить аргумент (будет ошибка компиляции).
2) Для указателя в аргументах функции можно указывать const до звездочки (константное значение указателя) и после звездочки (константный адрес указателя), тогда будет ошибка компиляции при попытке изменить значение или адрес указателя. Если указать только первый const (до звездочки) - то изменить адрес указателя можно будет внутри функции, но снаружи (переданный в функцию указатель) не изменит значения или адрес.
#include <iostream> // std::cout
using namespace std;
void func(int& arg){ // Функция принимает по ссылке аргумент
arg = 10; // Присваивание аргумента значения 10
}
void func_const_link(const int& arg){ // Функция принимает по ссылке аргумент определенный как константа
//arg = 10; // Ошибка! Нельзя менять константный аргумент
}
void func_const_ptr(const int* arg){ // Функция принимает константный указатель
//*arg = 10; // Ошибка! Нельзя менять значение константного указателя
arg = nullptr; // Изменять адрес можно, но это не имеет эффекта, внешний указатель не меняется...
}
void func_const_const_ptr(const int* const arg){ // Функция принимает константный указатель
//*arg = 10; // Ошибка! Нельзя менять значение константного указателя (первый const)
//arg = nullptr; // Ошибка! Нельзя менять адрес константного указателя (второй const)
}
int main(){
int a = 1; // Целочисленная переменная a
cout << "a = " << a << endl; //a = 1
func(a); // Передали a по ссылке в функцию и там изменили
cout << "a = " << a << endl; //a = 10
int* pa = &a; // Указатель на a
cout << "*pa = " << *pa << ", pa = " << pa << endl; //*pa = 10, pa = 0xb47e7ffb64
func_const_ptr(pa); // Передали указатель в функцию где ему меняют адрес
cout << "*pa = " << *pa << ", pa = " << pa << endl; //*pa = 10, pa = 0xb47e7ffb64 Значение и адрес указателя не изменились
const int* const pca = &a; // Константный указатель на a
cout << "*pca = " << *pca << ", pca = " << pca << endl; //*pca = 10, pca = 0xb47e7ffb64
//func(*pca); // Ошибка! Функция ожидает неконстантное значение
func_const_ptr(pca); // Передали указатель в функцию где ему меняют адрес
cout << "*pca = " << *pca << ", pca = " << pca << endl; //*pca = 10, pca = 0xb47e7ffb64 Значение и адрес указателя не изменились
}