Вопрос

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

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

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

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

Это было полезно?

Решение

Более простой пример: 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's.Они могут прыгать внутри foo() но это не имеет значения; foo() все еще должен вернуться.

Другие советы

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

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

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

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

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

или , если уж на то пошло

const int& a = a;

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top