Объявления в for-инструкции.
От: Forrest_Gump  
Дата: 11.02.04 00:14
Оценка:
Бьерн Страуструп "Язык программирования С++" Третье издание. стр. 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;

можно написать выше — до всех циклов, но всё-таки...
Re: Объявления в for-инструкции.
От: folk Россия  
Дата: 11.02.04 00:38
Оценка: 4 (2)
Здравствуйте, Forrest_Gump, Вы писали:

[]

F_G>Что это: недореализация стандарта С++ в MS Visual C++ или я что-то не понял у Страуструпа ?


F_G>А как было бы удобно для каждого for-цикла иметь свой счётчик с одним и тем же названием


Это особенность VC6, лечится так:
#define for if (false) {} else for

VC7 по умолчанию работает так же, но переводится в стандартный режим ключом /Zc:forScope или #pragma conform
На самом деле, люди не читают газеты, они принимают их каждое утро, так же как ванну. ©Маршалл Мак-Льюэн
Re: Объявления в for-инструкции.
От: pjeff Украина  
Дата: 11.02.04 00:45
Оценка: 2 (1)
Здравствуйте, Forrest_Gump, Вы писали:

[skipped]

имхо недореализация. Сам просто сталкивался с таким.

кста, в C# этого глюка нет, конструкция типа


void func()
{
  for( int i = 0 ; i < 10 ; i++ ) 
  {
    //code 
  }

  for( int i = 0 ; i < 12 ; i++ )
  { 
    //code 
  }
}


прокатывает на ура
Re: Объявления в for-инструкции.
От: Шахтер Интернет  
Дата: 11.02.04 02:30
Оценка: 2 (1)
Здравствуйте, Forrest_Gump, Вы писали:

F_G>Что это: недореализация стандарта С++ в MS Visual C++ или я что-то не понял у Страуструпа ?


В предыдущих версиях языка область видимости была шире. Потом по требованию публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.
... << RSDN@Home 1.1.0 stable >>
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: Объявления в for-инструкции.
От: Forrest_Gump  
Дата: 11.02.04 09:44
Оценка:
F>Это особенность VC6, лечится так:
F>#define for if (false) {} else for
Поясни, пожалуйста.
Не понимаю
Re[2]: Объявления в for-инструкции.
От: Forrest_Gump  
Дата: 11.02.04 09:53
Оценка:
Здравствуйте, Шахтер, Вы писали:
Ш>В предыдущих версиях языка область видимости была шире. Потом по требованию публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.
странно, что в Service Pack'ах это не поправили...
Re[3]: Объявления в for-инструкции.
От: Bell Россия  
Дата: 11.02.04 09:53
Оценка:
Здравствуйте, 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)
{
...
}
Любите книгу — источник знаний (с) М.Горький
Re: Объявления в for-инструкции.
От: Кодт Россия  
Дата: 11.02.04 12:25
Оценка:
Здравствуйте, Forrest_Gump, Вы писали:

<>

баг в VC6.
Лечится, как уже сказали, через
 #define for if(false) ; else for


написать #define for if(true) for
нельзя, так как в коде возможны конструкции
if(x)
  for(.....) { ..... }
else // if(x) else, а не if(true) else !!!
  .....
Перекуём баги на фичи!
Re[3]: Объявления в for-инструкции.
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 11.02.04 13:03
Оценка:
Здравствуйте, Forrest_Gump, Вы писали:

F_G>странно, что в Service Pack'ах это не поправили...

Ничего странного. Сервис-паки правят только ошибки, да и то не все. Данный случай ошибкой не являлся + совместимость с ранее написанным кодом требовалась.
Алексей Кирдин
Re[2]: Объявления в for-инструкции.
От: LaptevVV Россия  
Дата: 11.02.04 13:28
Оценка:
Здравствуйте, Кодт, Вы писали:

К>баг в VC6.

Не только. И борландовские этим грешили.
К>Лечится, как уже сказали, через
К>
 #define for if(false) ; else for


К>написать #define for if(true) for

К>нельзя, так как в коде возможны конструкции
К>
К>if(x)
К>  for(.....) { ..... }
К>else // if(x) else, а не if(true) else !!!
К>  .....
К>

Тогда надо просто писать

if (int i = 1) for (i = 0;...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Объявления в for-инструкции.
От: Кодт Россия  
Дата: 11.02.04 13:41
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Тогда надо просто писать

LVV>
LVV>if (int i = 1) for (i = 0;...
LVV>

не находишь, что тут что-то лишнее?
И, кстати, если это не int а объект с нетривиальным конструктором?..
Перекуём баги на фичи!
Re[4]: Объявления в for-инструкции.
От: LaptevVV Россия  
Дата: 11.02.04 13:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, LaptevVV, Вы писали:


LVV>>Тогда надо просто писать

LVV>>
LVV>>if (int i = 1) for (i = 0;...
LVV>>

К>не находишь, что тут что-то лишнее?
В сысле? Присвоение 1 — токмо для входа в for. А что она сама присваивает
И тем самым ограничиваем до конца тела цикла, поскольку из if тож выходим.
Что не так?
К>И, кстати, если это не int а объект с нетривиальным конструктором?..
Не, вопрос про for и переменную цикла стоял. А с конструктором не получится — он значения не возвращает. Обсуждался уже этот вопрос.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Объявления в for-инструкции.
От: Кодт Россия  
Дата: 11.02.04 14:07
Оценка:
Здравствуйте, LaptevVV, Вы писали:

К>>И, кстати, если это не int а объект с нетривиальным конструктором?..

LVV>Не, вопрос про for и переменную цикла стоял. А с конструктором не получится — он значения не возвращает. Обсуждался уже этот вопрос.

инициализация в стиле присваивания:
for(iterator it = cont.begin(); .....)
Перекуём баги на фичи!
Re[6]: Объявления в for-инструкции.
От: LaptevVV Россия  
Дата: 11.02.04 15:10
Оценка:
Здравствуйте, Кодт, Вы писали:

К>>>И, кстати, если это не 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 после всего.
Надо что-нить установить? Чтоб в точности по стандарту?
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Объявления в for-инструкции.
От: Павел Кузнецов  
Дата: 12.02.04 08:38
Оценка: 6 (1)
Здравствуйте, Шахтер, Вы писали:

Ш> В предыдущих версиях языка область видимости была шире. Потом по требованию

Ш> публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.

Не то, чтобы я утверждал, что разработчикам VC++6 нужно было обязательно
бросаться реализовывать новые правила видимости переменной цикла for, но,
справедливости ради, думаю, стоит заметить, что VC++6 вышел в 1998 году, в то
время как новые правила относительно for были приняты где-то в 1993 или 1994.
Т.е. решение оставить старые правила видимости переменной цикла for в VC++6 было
вполне сознательным, и неведением разработчиков о новых правилах не объясняется.

Надо отдать им должное, в следующих версиях они придумали элегантное решение
проблемы совместимости, позволив компилировать как код, написанный по старым
правилам, так и по новым без переключения всяких ключей компиляции и т.п.
Posted via RSDN NNTP Server 1.7 "Bedlam"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[7]: Объявления в for-инструкции.
От: Павел Кузнецов  
Дата: 12.02.04 08:47
Оценка: 3 (1)
Здравствуйте, LaptevVV, Вы писали:

L> Кстати, VS2003 тож не отслеживает по умолчанию.

L>
 L> int main()
 L> {
 L>  vector <int> v(10,2);
 L>  typedef vector <int>::iterator itfor;
 L>  for(itfor it = v.begin(); it < v.end(); it++) cout << *it << ' ';
 L>  cout << endl;
 L>  if (it == v.end()) cout << "out" << endl;
 L>  return 0;
 L> }
 L>

L> Выводит out после всего.

В этой (или предыдущей?) версии 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"
Легче одурачить людей, чем убедить их в том, что они одурачены. — Марк Твен
Re[3]: Объявления в for-инструкции.
От: jazzer Россия Skype: enerjazzer
Дата: 12.02.04 08:48
Оценка: 6 (1)
Здравствуйте, Павел Кузнецов, Вы писали:

ПК>Здравствуйте, Шахтер, Вы писали:


Ш>> В предыдущих версиях языка область видимости была шире. Потом по требованию

Ш>> публики её сузили. Не забывайте, что VC6 был сделан уже очень давно.

ПК>Не то, чтобы я утверждал, что разработчикам VC++6 нужно было обязательно

ПК>бросаться реализовывать новые правила видимости переменной цикла for, но,
ПК>справедливости ради, думаю, стоит заметить, что VC++6 вышел в 1998 году, в то
ПК>время как новые правила относительно for были приняты где-то в 1993 или 1994.
ПК>Т.е. решение оставить старые правила видимости переменной цикла for в VC++6 было
ПК>вполне сознательным, и неведением разработчиков о новых правилах не объясняется.

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

ПК>Надо отдать им должное, в следующих версиях они придумали элегантное решение

ПК>проблемы совместимости, позволив компилировать как код, написанный по старым
ПК>правилам, так и по новым без переключения всяких ключей компиляции и т.п.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.