Ссылочная инициализация в C ++ - PullRequest
1 голос
/ 20 августа 2009

Приветствую всех!

Изучив свой собственный код, я подошел к этой интересной строке:

const CString &refStr = ( CheckCondition() ) ? _T("foo") : _T("bar");

Теперь я в полном недоумении и не могу понять, почему это законно. Насколько я понимаю, константная ссылка должна быть инициализирована либо с r-значением, либо с l-значением. Неинициализированные ссылки не могут существовать. Но ()? Оператор выполняет функцию CheckCondition () перед тем, как назначить значение для ссылки. Теперь я вижу, что пока выполняется CheckCondition (), refStr существует, но все еще не инициализирован. Что произойдет, если CheckCondition () сгенерирует исключение или передаст управление с помощью оператора goto? Будет ли ссылка не инициализирована или я что-то упустил?

Ответы [ 6 ]

6 голосов
/ 20 августа 2009

Вы что-то упускаете - это полностью допустимый код, и на самом деле такой код является одним из наиболее распространенных и лучших вариантов использования условного оператора. Всегда ошибочно думать, что компилятор должен внутренне делать вещи в том же порядке, в котором код размещен на странице - он может свободно вычислять условный оператор (который является просто другим выражением) и затем использовать результат выполнить инициализацию.

Что касается goto, то его нельзя использовать при инициализации. И если выдается исключение, считается, что ссылка никогда не была создана в первую очередь.

5 голосов
/ 20 августа 2009

Более простой пример: const int x = foo();

Эту константу тоже нужно инициализировать, и для этого нужно вызвать foo(). Это происходит в необходимом порядке: x появляется только тогда, когда возвращается foo.

Чтобы ответить на ваши дополнительные вопросы: Если foo() будет throw, исключение будет где-то поймано catch(). Блок try{} для этого catch() явно окружен const int x = foo();. Следовательно, const int x уже выходит за рамки, и не имеет значения, что оно никогда не получало значение. И если нет catch для исключения, ваша программа (включая const int x) пропала.

C ++ не имеет случайных goto. Они могут прыгать в пределах foo(), но это не имеет значения; foo() все еще должен вернуться.

3 голосов
/ 20 августа 2009

Неинициализированные ссылки не могут существовать.

К сожалению, при инициализации можно делать забавные вещи. Вы могли бы также написать

const int& a = foobar(a) ? 1 : 2;

или по делу

const int& a = a;

Я полагаю, что когда компилятор работает слева направо, a действительно находится в области видимости справа, поэтому технически вы должны иметь возможность использовать его, и в лучшем случае он может предупредить:

"ComeauTest.c", строка 9: предупреждение: переменная "a" используется до установки ее значения

  const int& a = foobar(a) ? 1 : 2;
                        ^

Естественно, это может привести только к неопределенному поведению, как при использовании любой неинициализированной переменной.

Ваш пример в порядке, поскольку вы не используете ссылку до ее инициализации.

2 голосов
/ 20 августа 2009

Это полностью законно. Либо это заканчивается успешно, и ссылка привязывается к действительному объекту, либо выдается исключение, и управление передается за пределы блока, и ссылка больше не находится в области видимости, поэтому никто больше не заботится об этом.

2 голосов
/ 20 августа 2009

Теперь я вижу, что пока выполняется CheckCondition (), refStr существует, но все еще не инициализирован.

С точки зрения адвоката, это неправильно. Во время инициализации refStr еще не существует. Я предполагаю, что ваш визуальный отладчик дает вам вводящие в заблуждение подсказки.

Если код внутри инициализации приводит к условию ошибки, refStr не будет существовать и никогда не будет существовать.

0 голосов
/ 20 августа 2009

Исключение приведет вас в место, где refStr недоступен, и вы не сможете перейти туда, где оно находится оттуда. Goto не сможет выйти из CheckCondition (), если это функция, и вы не сможете использовать goto, если это макрос. Longjmp () будет иметь тот же эффект, что и исключение: вы попадете в место, где refStr недоступен.

...