Здесь переменная bufSize
определяется и инициализируется в файле file_1.cc
. Поскольку это объявление включает инициализатор, оно (как обычно) является и определением. Но поскольку bufSize
константа, необходимо применить ключевое слово extern
, чтобы использовать ее в других файлах.
Объявление в заголовке file_1.h
также использует ключевое слово extern
. В данном случае это демонстрирует, что имя bufSize
не является локальным для этого файла и что его определение находится в другом месте.
Чтобы совместно использовать константный объект в нескольких файлах, его необходимо определить с использованием ключевого слова extern
.
Упражнение 2.26. Что из приведенного ниже допустимо? Если что-то недопустимо, то почему?
(a) const int buf; (b) int cnt = 0;
(c) const int sz = cnt; (d) ++cnt; ++sz;
2.4.1. Ссылка на константу
Подобно любым другим объектам, с константным объектом можно связать ссылку. Для этого используется ссылка на константу (reference to const
), т.е. ссылка на объект типа const
. В отличие от обычной ссылки, ссылку на константу нельзя использовать для изменения объекта, с которым она связана.
const int ci = 1024;
const int &r1 = ci; // ok: и ссылка, и основной объект - константы
r1 = 42; // ошибка: r1 - ссылка на константу
int &r2 = ci; // ошибка: неконстантная ссылка на константный объект
Поскольку нельзя присвоить значение самой переменной ci
, ссылка также не должна позволять изменять ее. Поэтому инициализация ссылки r2
— это ошибка. Если бы эта инициализация была допустима, то ссылку r2
можно было бы использовать для изменения значения ее основного объекта.
Программисты С++, как правило, используют термин константная ссылка (const reference), однако фактически речь идет о ссылке на константу (reference to const).
С технической точки зрения нет никаких константных ссылок. Ссылка — не объект, поэтому саму ссылку нельзя сделать константой. На самом деле, поскольку нет никакого способа заставить ссылку ссылаться на другой объект, то в некотором смысле все ссылки — константы. То, что ссылка ссылается на константный или неконстантный тип, относится к тому, что при помощи этой ссылки можно сделать, однако привязку самой ссылки изменить нельзя в любом случае.
В разделе 2.1.2 мы обращали ваше внимание на два исключения из правила, согласно которому тип ссылки должен совпадать с типом объекта, на который она ссылается. Первое исключение: мы можем инициализировать ссылку на константу результатом выражения, тип которого может быть преобразован (см. раздел 2.1.2) в тип ссылки. В частности, мы можем связать ссылку на константу с неконстантным объектом, литералом или более общим выражением:
int i = 42;
const int &r1 = i; // можно связать ссылку const int& с обычным
// объектом int
const int &r2 =42; // ok: r1 - ссылка на константу
const int &r3 = r1 * 2; // ok: r3 - ссылка на константу
int &r4 = r * 2; // ошибка: r4 - простая, неконстантная ссылка
Простейший способ понять это различие в правилах инициализации — рассмотреть то, что происходит при связывании ссылки с объектом другого типа:
double dval = 3.14;
const int &ri = dval;
Здесь ссылка ri
ссылается на переменную типа int
. Операции со ссылкой ri
будут целочисленными, но переменная dval
содержит число с плавающей запятой, а не целое число. Чтобы удостовериться в том, что объект, с которым связана ссылка ri
, имеет тип int
, компилятор преобразует этот код в нечто следующее:
const int temp = dval; // создать временную константу типа int из
// переменной типа double
const int &ri = temp; // связать ссылку ri с временной константой