Бьерн Страуструп "Язык программирования С++" Третье издание. стр. 179
Параграф 6.3.3.1 Объявления в for-инструкции.
Переменную можно объявить в части инициализации инсрукции for. В этом случае область видимости переменной (или переменных) простирается до конца for-инструкции. Например:
void f(int v[], int max){
for(int i = 0; i < max; i++) v[i] = i*i;
}
Если требуется узнать значение индекса после выхода из цикла for, переменную надо объявить вне его (пример параграфа 6.3.4)
Проверяем цитату на практике:
for(int i = 0; i < 10; i++) std::cout << "test" << '\n';
for(int i = 0; i < 10; i++) std::cout << "test" << '\n';
В Visual Studio 6 SP5 получаем ошибку компиляции:
E:\KILL_ME\hjkhkj\main.cpp(28) : error C2374: 'i' : redefinition; multiple initialization
E:\KILL_ME\hjkhkj\main.cpp(27) : see declaration of 'i'
В то же время с if такой фокус проходит:
if(int i = a - b){};
if(int i = a - b){};
(Извините, ничего умнее не придумал — поздно уже )
Что это: недореализация стандарта С++ в MS Visual C++ или я что-то не понял у Страуструпа ?
А как было бы удобно для каждого for-цикла иметь свой счётчик с одним и тем же названием
Понимаю, что
int i;
можно написать выше — до всех циклов, но всё-таки...
[]
F_G>Что это: недореализация стандарта С++ в MS Visual C++ или я что-то не понял у Страуструпа ?
F_G>А как было бы удобно для каждого for-цикла иметь свой счётчик с одним и тем же названием
Это особенность VC6, лечится так:
#define for if (false) {} else for
VC7 по умолчанию работает так же, но переводится в стандартный режим ключом /Zc:forScope или #pragma conform
Здравствуйте, Шахтер, Вы писали: Ш>В предыдущих версиях языка область видимости была шире. Потом по требованию публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.
странно, что в Service Pack'ах это не поправили...
Здравствуйте, Forrest_Gump, Вы писали:
F>>Это особенность VC6, лечится так: F>>#define for if (false) {} else for F_G>Поясни, пожалуйста. F_G>Не понимаю
Если ты объявишь такой define, то препроцессор заменит строку
for(int i = 0; i < nSomeValue; ++i)
{
...
}
на
if(false)
{
}
else
for(int i = 0; i < nSomeValue; ++i)
{
...
}
т.е. for со всеми объявленными в init-секции попадет в скоуп оператора if, а значит i не будет видна за пределами этого if. Тогда спокойно моэно писать
for(int i = 0; i < nSomeValue; ++i)
{
...
}
for(int i = 0; i < nSomeValue; ++i)
{
...
}
Здравствуйте, Forrest_Gump, Вы писали:
F_G>странно, что в Service Pack'ах это не поправили...
Ничего странного. Сервис-паки правят только ошибки, да и то не все. Данный случай ошибкой не являлся + совместимость с ранее написанным кодом требовалась.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, LaptevVV, Вы писали:
LVV>>Тогда надо просто писать LVV>>
LVV>>if (inti = 1) for (i = 0;...
LVV>>
К>не находишь, что тут что-то лишнее?
В сысле? Присвоение 1 — токмо для входа в for. А что она сама присваивает
И тем самым ограничиваем до конца тела цикла, поскольку из if тож выходим.
Что не так? К>И, кстати, если это не int а объект с нетривиальным конструктором?..
Не, вопрос про for и переменную цикла стоял. А с конструктором не получится — он значения не возвращает. Обсуждался уже этот вопрос.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
К>>И, кстати, если это не int а объект с нетривиальным конструктором?.. LVV>Не, вопрос про for и переменную цикла стоял. А с конструктором не получится — он значения не возвращает. Обсуждался уже этот вопрос.
Здравствуйте, Кодт, Вы писали:
К>>>И, кстати, если это не int а объект с нетривиальным конструктором?.. К>инициализация в стиле присваивания: К>
К>for(iterator it = cont.begin(); .....)
К>
А ты хочешь сказать, что в таком варианте надо применять тот самый define. Согласен, но сам я буду искать способы попроще — уж очень мне такие выкрутасы с definom не по душе.
ИМХО, лучше уж просто в блок взять вес for, чтоб объект локальным стал. Только откомментарить.
Кстати, VS2003 тож не отслеживает по умолчанию.
int main()
{
vector <int> v(10,2);
typedef vector <int>::iterator itfor;
for(itfor it = v.begin(); it < v.end(); it++) cout << *it << ' ';
cout << endl;
if (it == v.end()) cout << "out" << endl;
return 0;
}
Выводит out после всего.
Надо что-нить установить? Чтоб в точности по стандарту?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, Шахтер, Вы писали:
Ш> В предыдущих версиях языка область видимости была шире. Потом по требованию Ш> публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.
Не то, чтобы я утверждал, что разработчикам VC++6 нужно было обязательно
бросаться реализовывать новые правила видимости переменной цикла for, но,
справедливости ради, думаю, стоит заметить, что VC++6 вышел в 1998 году, в то
время как новые правила относительно for были приняты где-то в 1993 или 1994.
Т.е. решение оставить старые правила видимости переменной цикла for в VC++6 было
вполне сознательным, и неведением разработчиков о новых правилах не объясняется.
Надо отдать им должное, в следующих версиях они придумали элегантное решение
проблемы совместимости, позволив компилировать как код, написанный по старым
правилам, так и по новым без переключения всяких ключей компиляции и т.п.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
В этой (или предыдущей?) версии Microsoft ввели очень хитрое поведение: по
умолчанию она "понимает" как старый, так и новый код. Т.е., если модифицировать
приведенный пример следующим обраом, то он все равно успешно скомпилируется:
int main()
{
vector <int> v(10,2);
typedef vector <int>::iterator itfor;
for(itfor it = v.begin(); it < v.end(); it++) cout << *it << ' ';
cout << endl;
for(itfor it = v.begin(); it < v.end(); it++) cout << *it << ' ';
return 0;
}
L> Надо что-нить установить? Чтоб в точности по стандарту?
В точности по стандарту — включить опцию компиляции /Zc:forScope.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Здравствуйте, Павел Кузнецов, Вы писали:
ПК>Здравствуйте, Шахтер, Вы писали:
Ш>> В предыдущих версиях языка область видимости была шире. Потом по требованию Ш>> публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.
ПК>Не то, чтобы я утверждал, что разработчикам VC++6 нужно было обязательно ПК>бросаться реализовывать новые правила видимости переменной цикла for, но, ПК>справедливости ради, думаю, стоит заметить, что VC++6 вышел в 1998 году, в то ПК>время как новые правила относительно for были приняты где-то в 1993 или 1994. ПК>Т.е. решение оставить старые правила видимости переменной цикла for в VC++6 было ПК>вполне сознательным, и неведением разработчиков о новых правилах не объясняется.
совершенно верно.
я даже когда-то видел их заявление по этому поводу, то ли в МСДН, то и на их сайте.
Суть заявления сводилась к тому, что им новые правила не нравятся по многим причинам
(главная из них — совместимость со старым кодом), и они сознательно их саботируют.
ПК>Надо отдать им должное, в следующих версиях они придумали элегантное решение ПК>проблемы совместимости, позволив компилировать как код, написанный по старым ПК>правилам, так и по новым без переключения всяких ключей компиляции и т.п.