Литеральная инициализация для константных ссылок - PullRequest
17 голосов
/ 18 января 2010

Как работает следующий код в C ++? Это логично?

const int &ref = 9;
const int &another_ref = ref + 6;

Почему C ++ допускает буквальную инициализацию для константных ссылок, если это не разрешено для неконстантных ссылок? E.g.:

const int days_of_week = 7;
int &dof = days_of_week; //error: non const reference to a const object

Это может быть объяснено тем фактом, что неконстантная ссылка может использоваться для изменения значения переменной, на которую она ссылается. Следовательно, C ++ не допускает неконстантную ссылку на константную переменную.

Может ли это быть возможным объяснением? C ++ не позволяет:

int &ref = 7;

Потому что это не логично, но:

const int &ref = 7;

Почти эквивалентно:

const int val = 7;

Так что буквальная инициализация разрешена для константных переменных.

П.С .: В настоящее время я изучаю учебник по С ++ для Липпмана.

Ответы [ 3 ]

11 голосов
/ 18 января 2010

Ссылки на константы могут быть инициализированы литералами и временными значениями, поскольку их можно легко преобразовать в явные переменные:

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);
}

(Обратите внимание на явный блок в этом случае.)

Хотя возможно сделать что-то подобное в неконстантном случае, это просто недопустимо в токе C ++.C ++ 0x (следующий стандарт), однако, будет иметь ссылки на r-значения.


Если неясно, ref + 6 из вашего кода создает временный объект, который вы можете визуализироватьas:

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;

Это может помочь вам понять / визуализировать происходящее, но вы не должны писать настоящий код, подобный этому.Также я использовал двойные имена подчеркивания, чтобы проиллюстрировать, что эти имена являются деталями реализации (используются компилятором) и не должны использоваться вами.Любое имя, которое содержит соседние подчеркивания, зарезервировано для реализации C ++.

9 голосов
/ 18 января 2010

Таким образом, вы можете написать код так:

void f( const string & s ) {
}

f( "foobar" );

Хотя, строго говоря, то, что на самом деле здесь происходит, не является литералом, привязанным к константной ссылке, - вместо этого создается объект временной строки:

string( "foobar" );

и эта безымянная строка привязана к ссылке.

Обратите внимание, что на самом деле довольно необычно создавать непараметрические ссылочные переменные, как вы это делаете - основная цель ссылок - служить параметрами функции и возвращаемыми значениями.

2 голосов
/ 18 января 2010

Ваш код сводится к стандартному правилу C ++, где время жизни временного значения связано со временем жизни ссылки const, которой оно назначено. См. GoTW статья ПОЛУЧИЛА № 88: Кандидат на «Важнейшее постоянное» для получения дополнительной информации.

Например, реализация ScopeGuard, описанная Александреску и Маргиняном в статье доктора Доббса « Generic: Изменить способ написания кода, исключающего исключение - навсегда », зависит от этого поведения.

...