LINUX.ORG.RU

[C++][goto]«Оператор goto перескакивает через конструктор» - это правда???

 


0

0

веревка достаточной длины чтобы выстрелить себе в ногу

Этот метод не срабатывает в С++, потому что функции конструктора вызываются неявно в качестве части объявления; объявление часто скрывает вызов функции. Если вы пропускаете объявление, то вы пропускаете и вызов конструктора. Например, в следующей программе деструктор для x вызовется, а конструктор нет:

foo()
{
if ( некое_условие )
goto выход;
некий_класс x; // Конструктор не вызывается. (Оператор goto
// перескакивает через него.)
// ...
выход:
// Здесь вызывается деструктор для x при выходе x из
// области видимости.
}
Вследствие этой проблемы лучше всего совсем избегать переходов goto в программах на С++.

★★★★★
Ответ на: комментарий от ovax

>Эх, молодежь...
>Не нюхала старого фортрановского кода на волшебных клубочках из GoTo..

На Фортране халява была. Там и IF'ы множественные, и вообще, ЯВУ...

Вот на Б3-21 программирование было эквилибристикой... Я, правда, его не застал, и программировать начал с МК-61, у которого система команд Б3-34 была. Там уже была халява :) А уж когда Бейсик пришёл с его GOTO и GOSUB, тогда программирование из эзотерики стало ремеслом.

KRoN73 ★★★★★
()
Ответ на: комментарий от Reset

> Про "рефакторинг" я уже устал сказки слушать. Давай конкретный пример. 

самый простой вариант вынести большие куски кода в отдельные функции, тогда можно будет написать 

if( ... ) { 
    ret = gamma0 
} 
else {
...
    do_something();
    if( ,,, ) {
       ret = ...;
    }
    else {
      ...
    }
}

free(..);
...
если вложенность if-ов слишком большая - выносить их тоже в отдельные функции, я понимаю огромный кусок кода на 500 строк тоже работает, но разбиение на функции полезно хотя бы с точки зрения удобства дебага, не говоря уже о том, что код легче читается
  
> нафиг нафиг сюда в чистый Си тянуть плюсы из-за того, что у кого-то есть религиозные претензии к goto.

я не знал, что у вас религиозные претензии к С++ - ок, smart_ptr отменяется

П.С. Есть великолепная книга - "Улучшение существующего кода" Мартин Фаулер, очень рекомендую
П.П.С. а вообще спорить про стиль программирования нет смысла, предлагаю перемирие :)

lester ★★★★
()
Ответ на: комментарий от lester

Абсолютно идиотский "рефакторинг".

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

LamerOk ★★★★★
()
Ответ на: комментарий от LamerOk

> В том куске кода собран и реализован четко очерченный функционал.

в том куске - метка и goto не нужны, они нужны выше( второй пример ), что нам это говорит - правильно, что функция очень большая, чтоб привести ее целиком

> Понять, что и как сделано из каши всяких do_something()


простите, но идиот тут вы, понять код:

init();

if( find( index ) > 0 )
do_Something( ... );
else
do_Another( ... );

куда проще чем, к примеру, 300 строк прямым текстом, если вы не догадались - имена функций в реальном коде будут осмысленными

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


если фунция не влазит даже в три экрана, а вы говорите, что она так лучше читается, то опять же вы ССЗБ

lester ★★★★
()
Ответ на: комментарий от LamerOk

>Понять, что и как сделано из каши всяких do_something() читающему код будет на порядок сложнее

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

KRoN73 ★★★★★
()
Ответ на: комментарий от lester

>простите, но идиот тут вы, понять код:

Он не идиот, он просто неопытный молодой агрессивный программист :) Ник у него соответствует. Но с опытом это проходит :)

KRoN73 ★★★★★
()
Ответ на: комментарий от lester

> самый простой вариант вынести большие куски кода в отдельные функции, тогда можно будет написать

Тогда теряется весь смысл "рефакторинга" -- код из понятного превращается в непонятный (конкретно в этом случае!).

> П.С. Есть великолепная книга - "Улучшение существующего кода" Мартин Фаулер, очень рекомендую

Как-нибудь гляну. Хотя уже много чего прочитал из подобной литературы и пришел к выводу, что всё написанное в тупую применять нельзя, а надо конкретно смотреть на свой случай.

> П.П.С. а вообще спорить про стиль программирования нет смысла, предлагаю перемирие :)

Согласен.

Reset ★★★★★
()
Ответ на: комментарий от KRoN73

>--i и i-- равно одинаково, 6.16сек.

>++i и i++ равно одинаково, 7.56сек.

Думаю, компилятор может соптимизировать i++ и заменить на ++i, если в данном контексте между ними нет разницы. Попробуй без оптимизации откомпилять и пробенчи ещё раз.

MYMUR ★★★★
()
Ответ на: комментарий от MYMUR

>Думаю, компилятор может соптимизировать i++ и заменить на ++i, если в данном контексте между ними нет разницы.

Безусловно. Хотя непонятна разница между i-- и --i.

>Попробуй без оптимизации откомпилять и пробенчи ещё раз.

А смысл без оптимизации-то? :)

KRoN73 ★★★★★
()
Ответ на: комментарий от legolegs

> Если у меня есть сто островов Буянов, на каждом растёт сто дубов, на которых по сто сундуков, в которых по сто зайцев, в каждом зайце по сто уток

А вот так делать - религия не даёт?

bool updatePath(int &path[]) {
...
}

int path[] = {0,0,0,0,0};
do {
...
} while (updatePath(path));

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

>А вот так делать - религия не даёт?

>bool updatePath(int &path[]) {

Когда мне надо было сделать перебор произвольной вложенности - я примерно так и поступил. Но использовать этот метод в общем случае - неэффективно.

legolegs ★★★★★
() автор топика
Ответ на: комментарий от Reset

> нафиг нафиг сюда в чистый Си тянуть плюсы

Стоп-стоп-стоп. Согласно заголовку, обсуждается именно C++.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

>Стоп-стоп-стоп. Согласно заголовку, обсуждается именно C++.

Это же ЛОР. С тезисом из заголовка мы разобрались ещё в первой трети первой странцы ("не скомпилируется").

legolegs ★★★★★
() автор топика
Ответ на: комментарий от lester

> если фунция не влазит даже в три экрана, а вы говорите, что она так лучше читается, то опять же вы ССЗБ

Где-то был хороший критерий - функция должна быть не больше головы. В прямом смысле: если приложить голову к монитору, функция должна быть не больше.

Miguel ★★★★★
()
Ответ на: комментарий от legolegs

> Но использовать этот метод в общем случае - неэффективно.

Ну да, ну да, premature ejacu^Woptimization - наш особый путь.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Не ищете лёгких путей? Надо сразу позакрученнее и, если получится, потормозней. "преждевременная оптимизация - корень всех зол! Буууу! Бабай придёт за тобой!"

legolegs ★★★★★
() автор топика
Ответ на: комментарий от legolegs

Когда альтернативой является каша из пяти for-ов - да, корень.

Это было по поводу второй фразы - единственной осмысленной в твоём комменте.

Miguel ★★★★★
()
Ответ на: комментарий от legolegs

Наоборот сначала надо проще. Другое дело, что "проще" у каждого своё, у кого то это блок-схема, перенесённая один в один, у кого то функция на 200 строк, у кого то декомпозированный по самое нехочу алгоритм.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

>Другое дело, что "проще" у каждого своё

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

legolegs ★★★★★
() автор топика
Ответ на: комментарий от legolegs

> Нет ничего проще пяти вложенных циклов в случае когда надо перебрать все комбинации значений пяти переменных

Нет ничего проще, чем не запоминать вообще количество переменных.

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

Я тут накропал быстренько вариант с вектором итераторов. Так вот он в ТРИ раза медленнее. При этом в функции updatePath количество переменных вшито в код. А если и его передавать как параметр...

legolegs ★★★★★
() автор топика
Ответ на: комментарий от legolegs

> Так вот он в ТРИ раза медленнее.

Ух ты, как интересно. А код можно посмотреть?

И, кстати, какую часть времени всё приложение проводит в этом куске с пятью форами?

Miguel ★★★★★
()
Ответ на: комментарий от Miguel

>> Так вот он в ТРИ раза медленнее. 
>Ух ты, как интересно. А код можно посмотреть?
Да пожалуйста. Остальная часть "тестового стенда" была выше.

//-------------------------------------
inline bool IncrPath(int path[], const int path_max[])
{
  path[0]++;
  for (int i = 0;i < 5;i++)
  {
    if (path[i] != path_max[i])
    {
      break;
    }
    path[i] = 0;
    path[i+1]++;
  }
  return (path[5] == 0);
}
void loops_vector()
{
  int path[] = {0, 0, 0, 0, 0, 0};
  const int path_max[] = {N, N, N, N, N};
  bool found = false;
  do
  {
    if ( some ( path[0], path[1], path[2], path[3], path[4] ) )
    {
      found = true;
      break;
    }
  }
  while (IncrPath(path, path_max));
  if (!found)
    throw NotFoundException();
  do_smth_with(path[0], path[1], path[2], path[3], path[4]);
}
//-------------------------------------

[legolegs@battlehummer src]$ nice -n -20 ./sandbox 100
loops_throw:    11.02
loops_goto:     10.94
loops_flag:     11.2
loops_goto_pp:  11.15
loops_throw_pp: 11.15
loops_counters: 10.89
loops_return:   10.99
loops_vector:   31.29

Предупреждая придирки: собрано с -O2 и инлайн работает (но не спасает).

legolegs ★★★★★
() автор топика
Ответ на: комментарий от KRoN73

> Безусловно. Хотя непонятна разница между i-- и --i.

Уже обсуждали. Если i является итератором, то --i будет быстрее i--. Достаточно глянуть на сорцы шаблона, что бы понять причину. Кстати, у Б. Страуструпа об этом сказано.

andreyu ★★★★★
()
Ответ на: комментарий от legolegs

> Предупреждая придирки: собрано с -O2 и инлайн работает (но не спасает).

Не удивительно. С таким то подходом:

> some ( path[0], path[1], path[2], path[3], path[4] )

> do_smth_with(path[0], path[1], path[2], path[3], path[4])


Да и от if (path[i] != path_max[i]) можно избавиться.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

>Не удивительно. С таким то подходом: >> some ( path[0], path[1], path[2], path[3], path[4] ) >> do_smth_with(path[0], path[1], path[2], path[3], path[4])

Эти функции используются ещё в пяти местах, так что переписывать их - не вариант. Кроме того some - тоже inline в данном случае.

>Да и от if (path[i] != path_max[i]) можно избавиться.

Ну предположим. Станет не в 3, а в 2.75 раз медленнее - какое щастье!

Одно дело - преждевременная оптимизация, другое - изначальный выбор сложного неэффективного решения.

PS если тут всё так просто и легко - приведите соответствующий код функции bool IncrPath(int path[], const int path_max[], int len).

legolegs ★★★★★
() автор топика
Ответ на: комментарий от legolegs

> Станет не в 3, а в 2.75 раз медленнее - какое щастье!

на самом деле хорошая разница, иногда и ради гораздо меньшего выигрыша приходится голову ломать :)

lester ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.