что плохого в объявлении переменной внутри условия if?
возможно, я становлюсь ржавым (недавно писал на Python).
почему это не компиляция?
if ( (int i=f()) == 0)
без ()
вокруг int i=f()
Я получаю еще одну, гораздо более разумную ошибку i
не логическое. Но именно поэтому я хотел скобки в первую очередь!
Я предполагаю, что использование круглых скобок делает его выражением, и что операторы объявления не допускаются в выражении. Так ли это? И если да, то это одна из синтаксических причуд C++?
кстати, я действительно пытался это сделать:
if ( (Mymap::iterator it = m.find(name)) != m.end())
return it->second;
4 ответов
вы можете объявить переменную в if
оператор в C++, но он ограничен для использования с прямой инициализацией, и его необходимо преобразовать в логическое значение:
if (int i = f()) { ... }
C++ не имеет ничего, что можно было бы описать как "выражение объявления", т. е. [sub-] выражения, объявляющие переменную.
на самом деле, я просто посмотрел предложение в стандарте, и обе формы инициализации поддерживаются в соответствии с 6.4 [stmt.выберите пункт 1:
...
condition:
expression
attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause
attribute-specifier-seqopt decl-specifier-seq declarator braced-init-list
...
то есть, также можно написать:
if (int i{f()}) { ... }
очевидно, что это работает только в C++2011, потому что C++2003 не имеет инициализации скобки.
есть проблема с областью.
рассмотрим следующий код:
if ((int a = foo1()) || (int b = foo2()))
{
bar(b);
}
объявлен ли b внутри блока? Что, если ... --1--> возвращает true?
вы можете объявить переменную в операторе if (или в for или while), но только во внешнем блоке скобок, и ее необходимо преобразовать в bool.
ваша догадка в основном права, это не разрешено, потому что
(int i = 42;)
не является допустимым объявлением с инициализацией.
вам нужна одна дополнительная линия,
Mymap::iterator it;
if ( (it = m.find(name)) != m.end())
return it->second;
но тогда лучше писать
Mymap::iterator it = m.find(name);
if ( it != m.end() )
return it->second;
вы можете поставить return
строке после if
, если вы действительно хотите вернуть эту строку, по крайней мере для меня это не вредит читаемости, но другие могут увидеть это по-другому.
если вы действительно хотите объявить итератор и использовать его как bool в if
условие, вы могли бы сделать
if ( struct { int it; operator bool() { return it != m.end; } } s = { m.find(name) } )
return s.it->second;
но я бы счел это вредным ; -)
Это правда, что вы не можете писать
if ( (int i=f()) == 0)
но вы можете прекрасно написать
if ( int i=f())
таким образом, вы можете использовать &&
оператор для выполнения обеих операций в одном операторе, как
if ( int i=1 && (i=f()) == 0)
i
должно быть инициализировано любым значением, отличным от 0, и это должно быть первое условие, если ваш компилятор применяет оценку слева направо.
но, к сожалению, это не применимо в случае итераторов в качестве второго примера спрашивает.