Литеральная инициализация для ссылок на const
Как работает следующий код на С++? Это логично?
const int &ref = 9;
const int &another_ref = ref + 6;
Почему С++ допускает литеральную инициализацию для ссылок const, когда то же самое не допускается для ссылок, не содержащих константы? Например:.
const int days_of_week = 7;
int &dof = days_of_week; //error: non const reference to a const object
Это можно объяснить тем, что для изменения значения переменной, к которой она обращается, может использоваться ссылка не const. Следовательно, С++ не допускает неконстантную ссылку на константную переменную.
Может ли это быть возможным объяснением? С++ не позволяет:
int &ref = 7;
Потому что это не логично, но:
const int &ref = 7;
Почти эквивалентен:
const int val = 7;
Для константных переменных допускается буквальная инициализация.
P.S.: В настоящее время я изучаю Lippman С++ Primer.
Ответы
Ответ 1
Итак, вы можете написать такой код:
void f( const string & s ) {
}
f( "foobar" );
Хотя, строго говоря, то, что на самом деле происходит здесь, не является литеральным, связанным с ссылкой на const, - вместо этого создается строковый объект:
string( "foobar" );
и эта безымянная строка привязана к ссылке.
Обратите внимание, что на самом деле довольно необычно создавать непараметрические ссылочные переменные, как вы это делаете - основная цель ссылок - служить параметрами функции и возвращаемыми значениями.
Ответ 2
Константные ссылки могут быть инициализированы литералами и временными, поскольку вы можете тривиально преобразовать их в явные переменные:
int const& ans = 42;
// tranformed:
int __internal_unique_name = 42;
int const& ans = __internal_unique_name;
Или, когда время жизни не расширено, например, параметр функции:
f("foobar");
// transformed:
{
string __internal_unique_name = "foobar";
f(__internal_unique_name);
}
(Обратите внимание на явный блок в этом случае.)
Хотя возможно сделать что-то подобное в непостоянном случае, что просто не разрешено в currenct С++. С++ 0x (следующий стандарт), однако, будет иметь ссылки r-значения.
Если неясно, ref + 6
из вашего кода создает временный объект, который вы можете визуализировать как:
int const& ref = int(9);
int const& another_ref = int(ref + 6);
// transformed:
int __A = 9;
int const& ref = __A;
int __B = ref + 6;
int const& another_ref = __B;
Это может помочь вам понять/визуализировать происходящее, но вы не должны писать настоящий код, как это. Кроме того, я использовал двойные подчеркивания, чтобы проиллюстрировать эти имена как детали реализации (используемые компилятором) и не должны использоваться вами. Любое имя, содержащее смежные подчеркивания, зарезервировано для реализации С++.
Ответ 3
Ваш код сводится к стандартному правилу С++, где время жизни временного значения привязано к времени жизни ссылки const
, которой она назначена. См. GoTW статья GotW # 88: Кандидат на "Most important const" для получения дополнительной информации.
Например, реализация ScopeGuard
, описанная Alexandrescu и Marginean в статье доктора Доббса "Generic: измените способ записи исключений Code - Forever "зависит от этого поведения.