Re[7]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 31.07.07 22:48
Оценка: +1
Здравствуйте, unreg_flex, Вы писали:

_>
_>template< class ValueType >
_>void EstimateContour(
_>


1. Глазоломный код. Именно для того чтобы не ломать глаза — люди давно придумали нормальные стандарты форматирования кода.
2. Некоторые переменные стоит инициализировать при создании. Например — Inv1,Inv2 и c.
3. Интересные названия. Например та же самая — с... Над названиями функций стоит поработать. Я бы ещё прибил венгерскую нотацию, но это дело привычки.
4.
_> std::vector< TGL::Circle< ValueType > > Circles;
_> [skip]
_> if(rPolygon.IsPointIn(c.Center())&&
_> rCirclesCond.Check(c)) Circles.push_back(c);
Этот фрагмент показывает, что goto в данной функции — самая что ни есть низкоуровневая и бесполезная оптимизация (если она затеяна с целью оптимизации). Допустим от одного только резервирования Circles скорее всего толку было бы больше. Подозреваю, что покопавшись можно найти ещё много интересных мест и решений.

NBN>>Я??? Где я предлагаю N4??? Я вообще не знаю что это за алгоритм и с какого перепугу это критический участок кода. Это кодек какой-то?

_>Не совсем, но нечто подобное.
Ничего подобного.

NBN>>Это прикидка — какая доля людей дрова пишет (0.05%).

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

_>stl используем везде где это возможно, однако до сих пор ни у кого в коде даже не нашлось нормальное применение обычным спискам из стл.

Бывает такое дело

_>Исключения не используем вообще, и более того, открою страшный секрет

_>Мы два года назад отказались от проверок на ошибки выделения памяти
_>И с тех пор ни разу, ни одна из наших програм не упала по этой причине.
Может вы просто не засекли? Впрочем это сильно зависит от программы, если бы они были достаточно сложными — такие проблемы были-бы навернякая (либо срок разработки в 2 больше).

_>А насчет смартпоинтеров скажу:

_>А других применений для него так и не нашлось.
Пожизненная узкая специализация?

_>Однажды, очень давно, на старом месте работы (не скажу где) люди шарахались с ужасной гримасой от строчки вида: SomeType *p;

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

NBN>>По твоему это типа так?

NBN>>
NBN>>for(int i=0;i<n1;++i){for(int j=0;j<n2;++j){if(c1)goto next1;for(int k=0;k<n3;++k){if(c2)goto next2;}}next2:;}next1:;
NBN>>

_>Не надо утрировать, ни я, ни кто-либо из нашей команды такого не писал.
Ты что то подобное привёл в качестве примера.

NBN>>Судя по отсуствию пробелов в for'ах действительно лаконично написано...

_>Пробелы в форах это так?: for ( int i = 0; i < n; ++i ) { }
_>Что я могу тут сказать, в нашем отделе работает 6 человек и многие пишут по разному:
_>Например так:
_>
_>

_>И никто никому не парит моск о том как надо расставлять пробелы, переносить строчки делать отступы
_>и заниматься прочей ерундой, все пишут так как привыкли.
_>И знаешь что удивительно? Никто никогда не жаловался на плохую читабельность
Маловероятно. Более того — не очень хорошо характеризует менеджмент.
Имхо самый лучший подход — либо чёткая спецификация всех нюансов кода (для больших контор) или правило: один проект — один стиль (для маленьких). По моим наблюдениям такой разброд в коде говорит о том, что когда человек его написавший уйдет — код выкинут.

NBN>>>>GOTO для выхода из вложенных циклов? По хорошему эти циклы должны разноситься на отдельные функции.

NBN>>Использую, правда два вложенных — это максимум на одну функцию и в дальнейшем это очень часто подвергается рефакторингу.
_>Параноидальное разнесение вложенных циклов на функции?
Нет, требование читабельности и поддерживаемости. См. Фаулера. Прикинь что будет, если другой человек, незнакомый с кодом — попытается в нём что то исправить.

_>PS Любые, даже самые хорошие советы содержат исключения. Тем же свойством обладают и советы в книгах.

Кто бы спорил Только это не тот случай.

_>Поэтому если пишут что делать нужно так и сяк, то это вовсе не значит что надо поступать именно так и именно сяк фанатично и всегда.

Фанатично не надо, но надо всегда следовать определённым правилам, особенно работая в коллективе. По крайней мере исключения должны чётко обосновываться. goto в данном случае — не является оптимизирующим явлением.

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

template< class ValueType >
class ContourEstimator
{
    typedef TGL::Point< ValueType, 2 >  TPoint;
    typedef TGL::Polygon< ValueType, 2 >TPolygon;
    typedef TGL::Circle< ValueType >    TCircle;
    typedef std::vector<TCircle>        TCircles;
public:

    ContourEstimator(
        const TPoint* points,
        int count_of_points,
        const TPolygon& polygon,
        const CirclesCondition& circlesCond,
        const PointsCondition& pointsCond
        )
        : points(points)
        , count_of_points(count_of_points)
        , polygon(polygon)
        , circlesCond(circlesCond)
        , pointsCond(pointsCond)
        , inv1(points[0])
        , inv2(points[0])
    {
        circles.reserve( count_of_points );
    }

    void EstimateContour()
    {
        for(int i = 0; i < count_of_points; ++i)
        {
            // отбрасываем точки вне оболочки
            if( !polygon.IsPointIn( points[i] ) )
                continue;
            if ( !EstimateContourDim2( i ) )
                break;
        }
        EstimateHull( circles, points, count_of_points );
    }

private:
    TCircles        circles;
    TPoint          inv1, inv2;
    const TPoint*   points;
    size_t          count_of_points;
    const TPolygon& polygon;

    const CirclesCondition& circlesCond;
    const PointsCondition&  pointsCond;


    bool EstimateContourDim2(int i)
    {
        for(int j = i + 1; j < count_of_points; ++j)
        {
            // первое условие двойственности
            if( !circlesCond.CheckFirst( points[i], points[j], pointsCond ) )
                return false;

            if( !EstimateContourDim3( i, j ) )
                return false;
        }
        return true;
    }

    bool EstimateContourDim3(int i, int j)
    {
        pointsCond.Invert( inv1, points[j] );

        for(int k = j + 1; k < count_of_points; ++k)
        {
            // второе условие двойственности
            if( !circlesCond.CheckSecond( points[j], points[k], pointsCond ) )
                return false;
            pointsCond.Invert( inv2, points[k] );

            TCircle circle;
            circle.Estimate( points[i], points[j], points[k] );
            circle.Refine( inv1, inv2 );
            // сохраняем если центр окружности принадлежит оболочке
            // и найденные параметры входят в заданный диапазон
            if( polygon.IsPointIn( circle.Center() ) && circlesCond.Check( circle ) )
                circles.push_back( c );
        }
        return true;
    }
};
Нужно разобрать угил.
Re[2]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 31.07.07 22:59
Оценка:
Здравствуйте, Пётр Седов, Вы писали:

ПС>2. goto вперёд. Это нормально, примеры (для C++):

ПС>* return в середине функции – досрочно завершить выполнение функции и передать управление на строчку за вызовом функции.
ПС>* break в цикле – досрочно завершить выполнение цикла и передать управление на строчку за циклом.
ПС>* continue – досрочно завершить выполнение итерации цикла и передать управление на следующую итерацию. А если следующей итерации нет, то передать управление на строчку за циклом.
ПС>* throw (и longjmp) – досрочно завершить выполнение кода (обычно из-за аварии) и передать управление обработчику исключения (блок catch).

А при чём тут goto?
Нужно разобрать угил.
Re[3]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 31.07.07 23:04
Оценка:
Здравствуйте, netch80, Вы писали:

N>1. Завершение работы функции с освобождением занятого и возвратом изменённого, для избежания дублирования кода по освобождению/очистке/возврату (потому что такое дублирование приводит к ошибкам в ~99% написаний).

Такие вещи необходимо вешать на автоматическое уничтожение. Неоднократно находил у людей ошибки связанные с таким подходом.

N>2. Близко к первому — постепенный откат изменений в том случае, если действий много, откатывать их надо в обратном порядке, а вложенность в случае структурного написания получится чрезмерной.

Автоматика

N>3. Почти на ту же тему — объединение веток завершения функции, но не с очисткой, а с сообщением об ошибке.

Вынос в функцию?

N>4. Выход из глубокой вложенности циклов или if'ов на выделенную ветку выполнения или сразу за конец внешнего из покинутых циклов.

Плохой стиль, тут нужно не готу, а рефакторинг.

N>5. Переход (обычно только вперёд) по длинной линейной последовательности действий, строить которую в виде ветвлений или автомата (while+switch) означает нарушить восприятие кода.

Разбивать на функции.

N>Но при наличии более продвинутых средств, чем голый Си, 1-3 можно перевалить на классы и RAII;

О, точно. Мне казалось что мы говорим про С++
Нужно разобрать угил.
Re[4]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 31.07.07 23:08
Оценка: -1
Здравствуйте, Programador, Вы писали:

N>>обосновывать и стараться применять пореже — их неудобно поддерживать. А если мы при этом обходим, например, инициализации переменных — такое писать нельзя ни в коем случае.

P>А и не позволят, если они конечно локальные. Деструкторы же по goto наружу кажется зовутся
Вроде бы микрософт специфик.
Нужно разобрать угил.
Re[8]: Существуют ли задачи, где использование GOTO оправдан
От: Programador  
Дата: 31.07.07 23:14
Оценка: -2
Здравствуйте, NikeByNike, Вы писали:
NBN>
NBN>template< class ValueType >
NBN>class ContourEstimator



NBN>};
NBN>

Этот код не эквивалентен исходному. Вы лихо перенесли автоматические объекты в приватную часть класса. А время жизни?

Если даже на это не смотреть, то область видимости расширилась на другие методы. И потом исходный код на экран помещался а этот 2 раза перелистывать нужно В общем ф топку
Re[5]: Существуют ли задачи, где использование GOTO оправдан
От: Programador  
Дата: 31.07.07 23:18
Оценка:
Здравствуйте, NikeByNike, Вы писали:

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


N>>>обосновывать и стараться применять пореже — их неудобно поддерживать. А если мы при этом обходим, например, инициализации переменных — такое писать нельзя ни в коем случае.

P>>А и не позволят, если они конечно локальные. Деструкторы же по goto наружу кажется зовутся
NBN>Вроде бы микрософт специфик.
А вооще вопрос занятный
Re[9]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 31.07.07 23:47
Оценка:
Здравствуйте, Programador, Вы писали:

P>Этот код не эквивалентен исходному. Вы лихо перенесли автоматические объекты в приватную часть класса. А время жизни?


Я постарался его учесть. Если ты про TGL::Circle< ValueType > c; то я сделал допущение, что на функцию c.Estimate( points[i], points[j], points[k] ); не влияет предыдущее состояние объекта с.
Остальное вроде правильно, с поправкой на то, что состояние аргументов функции не изменится между вызовами конструктора и EstimateContour. Кстати, на таком подходе иногда удаётся ускорить функции в разы. Допустим, если есть проверка пересечения луча с большим количеством боксов — замена функции на функтор — даёт приличное ускорение.

P>Если даже на это не смотреть, то область видимости расширилась на другие методы. И потом исходный код на экран помещался а этот 2 раза перелистывать нужно В общем ф топку


Отдельные функции стали меньше. То что код был в виде кирпича — не означало его лучшей читабельности. Вот тебе другой пример
Даже чуть короче исходного, видимо — чуть читабельнее?

template< class ValueType >
struct ContourEstimator {
 typedef TGL::Point< ValueType, 2 >TPt;
 typedef TGL::Polygon< ValueType, 2 >TPn;
 ContourEstimator(const TPt* p,size_t cp,const TPn& pn,const CirclesCondition& cc,const PointsCondition& pc)
 : points(p), cpoint(cp), polygon(pn), circlesCond(cc), pointsCond(pc), inv1(p[0]), inv2(p[0]) {}
 void EstimateContour(){
  for(size_t i=0; i<cpoint; ++i){
   // отбрасываем точки вне оболочки
   if( !polygon.IsPointIn( points[i] ) )continue;
   if( !EstimateContourDim2( i ) )break;
  }
  EstimateHull( circles, points, cpoint );
 }
 std::vector<TGL::Circle< ValueType >> circles;
 TPt inv1, inv2;
 const TPt* points;
 size_t cpoint;
 const TPn& polygon;
 const CirclesCondition& circlesCond;
 const PointsCondition&  pointsCond;
 bool EstimateContourDim2(size_t i){
  for(size_t j=i+1; j<cpoint; ++j){
   // первое условие двойственности
   if(!circlesCond.CheckFirst(points[i],points[j],pointsCond)||!EstimateContourDim3(i,j))return false;
  }
  return true;
 }
 bool EstimateContourDim3(size_t i, size_t j){
  pointsCond.Invert( inv1, points[j] );
  for(size_t k=j + 1; k<cpoint; ++k){
   // второе условие двойственности
   if( !circlesCond.CheckSecond( points[j], points[k], pointsCond ) )return false;
   pointsCond.Invert( inv2, points[k] );
   TGL::Circle< ValueType > c;
   c.Estimate( points[i], points[j], points[k] );
   c.Refine( inv1, inv2 );
   // сохраняем если центр окружности принадлежит оболочке
   // и найденные параметры входят в заданный диапазон
   if( polygon.IsPointIn( c.Center() ) && circlesCond.Check( c ) )circles.push_back( c );
  }
  return true;
 }
};
Нужно разобрать угил.
Re[10]: Существуют ли задачи, где использование GOTO оправда
От: NikeByNike Россия  
Дата: 31.07.07 23:48
Оценка:
Здравствуйте, NikeByNike, Вы писали:

P>>Этот код не эквивалентен исходному. Вы лихо перенесли автоматические объекты в приватную часть класса. А время жизни?


NBN>Я постарался его учесть.


В смысле — время жизни учесть...
Нужно разобрать угил.
Re[3]: Существуют ли задачи, где использование GOTO оправдан
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.08.07 05:59
Оценка: +1
Здравствуйте, NikeByNike, Вы писали:

NBN>Здравствуйте, Пётр Седов, Вы писали:


ПС>>2. goto вперёд. Это нормально, примеры (для C++):

ПС>>* return в середине функции – досрочно завершить выполнение функции и передать управление на строчку за вызовом функции.
ПС>>* break в цикле – досрочно завершить выполнение цикла и передать управление на строчку за циклом.
ПС>>* continue – досрочно завершить выполнение итерации цикла и передать управление на следующую итерацию. А если следующей итерации нет, то передать управление на строчку за циклом.
ПС>>* throw (и longjmp) – досрочно завершить выполнение кода (обычно из-за аварии) и передать управление обработчику исключения (блок catch).

NBN>А при чём тут goto?


При том, что всё это тоже формы goto, но ограниченные в направлении перехода, и потому допускаемые большинством разработчиков как "меньшее зло".
The God is real, unless declared integer.
Re[4]: Существуют ли задачи, где использование GOTO оправдан
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.08.07 06:02
Оценка:
Здравствуйте, NikeByNike, Вы писали:

N>>3. Почти на ту же тему — объединение веток завершения функции, но не с очисткой, а с сообщением об ошибке.

NBN>Вынос в функцию?

Неудобно. Макрос ещё как-то годится, но не это.

N>>4. Выход из глубокой вложенности циклов или if'ов на выделенную ветку выполнения или сразу за конец внешнего из покинутых циклов.

NBN>Плохой стиль, тут нужно не готу, а рефакторинг.

Аргументы?

N>>5. Переход (обычно только вперёд) по длинной линейной последовательности действий, строить которую в виде ветвлений или автомата (while+switch) означает нарушить восприятие кода.

NBN>Разбивать на функции.

Крайне неудобно поддерживать результат (в тех случаях, когда видел подобное в применении).
The God is real, unless declared integer.
Re[3]: Существуют ли задачи, где использование GOTO оправдан
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.08.07 06:50
Оценка: +3
Здравствуйте, Programador, Вы писали:

P>Здравствуйте, Нэчер, Вы писали:


Н>>
Н>>  c=a+b;

Н>>  //А теперь проверим - было ли переполнение?
Н>>  __asm
Н>>  {
Н>>    jc CarryFlag 
Н>>  }

Н>>}
Н>>

P>За это 5 баллов! А если кому не понравится пусть напишет проверку на переполнение в рамках стандарта

jIMHO — не 5, а максимум 3, и то сомнительно. Потому что 1) код всё равно платформенно-зависим, 2) нет достаточных причин предполагать, что сложение будет вообще выполнено именно таким методом, как нужен для последующего применения jc, 3) нет гарантии, что это сложение вообще не будет убрано или переоптимизировано. Например, имея код вида

d = a + b + c;
leftfunc(d);
c = a + b;
__asm { jc... }


второе присваивание будет выброшено, как повторяющее часть первого, а в CF останется то, что туда попало от leftfunc(). MS явно пишет в документации: "In general, you should not assume that a register will have a given value when an __asm block begins. Register values are not guaranteed to be preserved across separate __asm blocks." Flags — это тоже регистр.

Так что автор того кода ходит по верёвке над пропастью, причём в шторм. Частично это объясняется (не оправдывается) тупизной встроенного ассемблера MS, который, в отличие от gcc или Watcom, не даёт внятно объяснить "сюда загрузить a, сюда b, регистры модифицированы eax и Flags". Но даже в этом случае лучше было бы записать примерно так:

__asm {
  mov eax,[a]
  add eax,[b]
  jc CarryFlag
}


это бы дало гарантированную проверку CF именно от сложения, а не неизвестно от чего.

Если бы такая задача (складывать с проверкой на переполнение) стояла у меня, я бы
1) взял (если есть возможность) компилятор пограмотнее (типа gcc)
2) сделал бы inline-функцию, в которой ассемблером бы нарисовал код, соответствующий предыдущему (хотя, может быть, не jc, а что-то типа mov eax,0; rol eax,1 — чтобы выбрать CF в регистр без ветвления, которое замедляет процессор), и расставил бы ей адекватные constraint'ы (что куда загрузить, что модифицируется), получив бы примерно следующее:

inline
bool // 0 - нет переполнения, 1 - переполнение
unsigned_check_add(unsigned a, unsigned b)
{
  unsigned r;
  asm(
    "mov eax,%1\n"
    "add eax,%2\n"
    "mov eax,0\n"
    "rol eax,1"
    : "=a"(r) // результат брать из eax
    : "m"(a), "m"(b) // входные данные могут быть в памяти или в стеке, не важно
    : "cc" // побочный эффект - модификация Flags
  );
  return r;
}


Вот если у кого-то только MSVC — ну что ж, придётся извращаться потяжелее:(
The God is real, unless declared integer.
Re: Существуют ли задачи, где использование GOTO оправдано?
От: ionicman  
Дата: 01.08.07 07:33
Оценка: 9 (1) +1
Хорошая тема для обсуждения — это типа HolyWars-а почти
Я вот не понимал никогда, какого черта люди так говорят типа goto — плохой код и все такое.
По очень простой пречине — язык — это инструмент. Вам его дали, Вы им пользуетесь.
Если Вы находите удобным воспользоваться goto — пользуйтесь, если Вам удобно сделать функцию, либо же break — делайте.

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

Примеров полно — я не раз всречал умопомрачительные конструкции для перепрыгивания в циклах — когда есть несколько вложенных циклов и надо скажем из внутреннего 3-го прыгнуть в 1. Там и смарты использовались, и функции хиьтрые которые внутри себя эти циклы по частям крутили — а смысл? Использовать указатель за место goto — это же конечно более "гладкий" код :D

Апогеем маразма я видел когда переход осуществлялся программирование указателя и вызовом его как фии — мужик точно на асме раньше писал... полиморфы...

Вобщем, никого же не возмущает наличие в инструментах молотка? Ни кто ж не говорит что молоток — это не гуманно, лучше использовать отвертку ) Вам дали инструменты — пользуйтесь так как считаете нужным. А то началось — плохооо, когд не читаемый. Вот с Венгенрской нотацией код более читаемый — а че ее так мло используют? :D

ИМХО — goto очень удобный инструмент при переходе внутри вложенных циклов. Ибо стандартно в C нет continue метка или break метка. А использовать флажки, как предлагалось выше — это кончено верх изящества ))))
Re[8]: Существуют ли задачи, где использование GOTO оправдан
От: unreg_flex  
Дата: 01.08.07 07:53
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>1. Глазоломный код. Именно для того чтобы не ломать глаза — люди давно придумали нормальные стандарты форматирования кода.

Повторюсь, "нормальные стандарты форматирования кода" у всех свои.

NBN>2. Некоторые переменные стоит инициализировать при создании. Например — Inv1,Inv2 и c.

NBN>3. Интересные названия. Например та же самая — с... Над названиями функций стоит поработать. Я бы ещё прибил венгерскую нотацию, но NBN>это дело привычки.
Ага, ведь люди давно придумали нормальные стандарты именования переменных .
"Например та же самая — с", интересно, вы переменную в цикле называете i, n, или nVeryGoodCycleCounter?

NBN>Этот фрагмент показывает, что goto в данной функции — самая что ни есть низкоуровневая и бесполезная оптимизация (если она затеяна с целью NBN>оптимизации).

Кто вам сказал что гото тут для оптимизации?

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

От резервирования Circles толку небудет, поскольку их общее количество редко бывает >8.

NBN>Подозреваю, что покопавшись можно найти ещё много интересных мест и решений.

Подозреваю что нет, ничего интересного вы пока не нашли.

_>>Не совсем, но нечто подобное.

NBN>Ничего подобного.
oO, вы в курсе чем я занимаюсь?

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

Одного никак не пойму, почему оператор гото, то постоянно связывается с "абсолютной скоростью", то с форматированием кода.

NBN>Пожизненная узкая специализация?

Угу, неговорите

NBN>Обычно бывает наоборот, подтверждалось неоднократно и множеством людей, а именно — переход на автоматическое управление памятью NBN>снижало количество ошибок в разы. Ошибаются все, даже супер гуру. Опять же автоматическое управление памятью — существенно ускоряет NBN>разработку и чистоту кода. Допустим позволяет отказаться от деструкторов.

Полностью со всем согласен, но только не "автоматическое" управление памятью на C++
NBN>Вы видимо исключение
Я так не думаю.

NBN>>>По твоему это типа так?

NBN>>>
NBN>>>for(int i=0;i<n1;++i){for(int j=0;j<n2;++j){if(c1)goto next1;for(int k=0;k<n3;++k){if(c2)goto next2;}}next2:;}next1:;
NBN>>>

_>>Не надо утрировать, ни я, ни кто-либо из нашей команды такого не писал.
NBN>Ты что то подобное привёл в качестве примера.
Да вы мастер цитирования


NBN>>>Судя по отсуствию пробелов в for'ах действительно лаконично написано...

NBN>Маловероятно. Более того — не очень хорошо характеризует менеджмент.
NBN>Имхо самый лучший подход — либо чёткая спецификация всех нюансов кода (для больших контор) или правило: один проект — один стиль (для NBN>маленьких). По моим наблюдениям такой разброд в коде говорит о том, что когда человек его написавший уйдет — код выкинут.
Выкинут код или не выкинут зависит не от того как его автор расставлял пробельчики и скобочки.
А по моим наблюдениям для вас это первый критерий качества кода.

NBN>Фанатично не надо, но надо всегда следовать определённым правилам, особенно работая в коллективе. По крайней мере исключения должны NBN>чётко обосновываться. goto в данном случае — не является оптимизирующим явлением.

Нет слов, где я писал что "гото здесь является оптимизирующим явлением"?

NBN>Если это действительно критическое место — можно убрать выделения памяти, возможно немного изменить расчёты (похоже, что некоторые NBN>вещи можно вынести за пределы цикла), возможно — улучшить алгоритм (допустим за счёт какого-нибудь пространственного хеша). Лично я NBN>бы записал бы примерно в таком стиле (видимо так же подобрал бы другие названия и вынес бы функции за пределы класса):


Тут практически нет выделений памяти, и алгоритм не улучшить (так же как не улучшить прямой поиск в массиве без предобработки).

NBN>
NBN>template< class ValueType >
NBN>class ContourEstimator
NBN>{
NBN>    typedef TGL::Point< ValueType, 2 >  TPoint;
NBN>    typedef TGL::Polygon< ValueType, 2 >TPolygon;
NBN>    typedef TGL::Circle< ValueType >    TCircle;
NBN>    typedef std::vector<TCircle>        TCircles;
NBN>public:

// а это зачем? Чтобы запутать получше?  тому кто читает привычней видеть стандартные записи std::vector< TGL::Circle< ValueType > >

NBN>    ContourEstimator(
NBN>        const TPoint* points,
NBN>        int count_of_points,
NBN>        const TPolygon& polygon,
NBN>        const CirclesCondition& circlesCond,
NBN>        const PointsCondition& pointsCond
NBN>        )
NBN>        : points(points)
NBN>        , count_of_points(count_of_points)
NBN>        , polygon(polygon)
NBN>        , circlesCond(circlesCond)
NBN>        , pointsCond(pointsCond)
NBN>        , inv1(points[0])
NBN>        , inv2(points[0])
NBN>    {
NBN>        circles.reserve( count_of_points );
NBN>    }

// точек может быть миллионы, а окружностей 5-8.

NBN>    void EstimateContour()
NBN>    {
NBN>        for(int i = 0; i < count_of_points; ++i)
NBN>        {
NBN>            // отбрасываем точки вне оболочки
NBN>            if( !polygon.IsPointIn( points[i] ) )
NBN>                continue;
NBN>            if ( !EstimateContourDim2( i ) )
NBN>                break;
NBN>        }
NBN>        EstimateHull( circles, points, count_of_points );
NBN>    }

NBN>private:
NBN>    TCircles        circles;
NBN>    TPoint          inv1, inv2;
NBN>    const TPoint*   points;
NBN>    size_t          count_of_points;
NBN>    const TPolygon& polygon;

NBN>    const CirclesCondition& circlesCond;
NBN>    const PointsCondition&  pointsCond;


NBN>    bool EstimateContourDim2(int i)
NBN>    {
NBN>        for(int j = i + 1; j < count_of_points; ++j)
NBN>        {
NBN>            // первое условие двойственности
NBN>            if( !circlesCond.CheckFirst( points[i], points[j], pointsCond ) )
NBN>                return false;

NBN>            if( !EstimateContourDim3( i, j ) )
NBN>                return false;
NBN>        }
NBN>        return true;
NBN>    }

NBN>    bool EstimateContourDim3(int i, int j)
NBN>    {
NBN>        pointsCond.Invert( inv1, points[j] );

NBN>        for(int k = j + 1; k < count_of_points; ++k)
NBN>        {
NBN>            // второе условие двойственности
NBN>            if( !circlesCond.CheckSecond( points[j], points[k], pointsCond ) )
NBN>                return false;
NBN>            pointsCond.Invert( inv2, points[k] );

NBN>            TCircle circle;
NBN>            circle.Estimate( points[i], points[j], points[k] );
NBN>            circle.Refine( inv1, inv2 );
NBN>            // сохраняем если центр окружности принадлежит оболочке
NBN>            // и найденные параметры входят в заданный диапазон
NBN>            if( polygon.IsPointIn( circle.Center() ) && circlesCond.Check( circle ) )
NBN>                circles.push_back( c );
NBN>        }
NBN>        return true;
NBN>    }
NBN>};
NBN>


И чем теперь код стал лучше?
Тем что увеличился в 2 раза?
Увеличилась читабельность? o_O (ах да, пробельчики добавились, только не везде почему-то)
А может тем что напихали в класс кучу ненужных переменных имеющих смысл только в момент вызова этого метода?
Или новыми ненужными копированиями, кстати не малого объема данных?
А после отработки этого метода, скопированные данные останутся висеть в памяти?
Особенно весело копирование указателя
Re[2]: Существуют ли задачи, где использование GOTO оправдан
От: AndrewJD США  
Дата: 01.08.07 08:33
Оценка: :))
Здравствуйте, Нэчер, Вы писали:


Н>2) Есть один замечательный трюк с метками (помню, что точно работало в VC6.0):

Н>
Н>bool add(int a,int b,int& c)
Н>{
Н>  c=a+b;

Н>  //А теперь проверим - было ли переполнение?
Н>  __asm
Н>  {
Н>    jc CarryFlag 
Н>  }

Н>  //no carry
Н>  return 0;

Н>  CarryFlag:;

Н>  //carry
Н>  return 1;
Н>}
Н>


Н>Если подойти к вопросу трезво, то можно о-го-го сколько наоптимизировать в разного рода вычислительных алгоритмах =)


А не боишься, что потом коллега, который будет это сопровождать, подкараулит тебя где-нибудь в темном месте с тяжелым предметом?
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Re[2]: Существуют ли задачи, где использование GOTO оправдан
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 01.08.07 09:21
Оценка:
Здравствуйте, ionicman, Вы писали:

I>Я благодарен Страуструпу что он не пошел на поводу вот у таких "правильных" молодцев, которые считают, что "так правильней". Все зависит от конкретной задачи — для каждой из них — свой инструмет. Можно ведь и гаечным ключом гвоздь то забить.


Страуструп сильно непоследователен. goto он разрешил, у которого есть значительные проблемы в реализации (например, та же тема с конструкторами объектов, когда переход происходит в середину блока, или чуть попроще — при выходе по goto из блока) — тут уже проблемы с этим обсуждали. А вот значительно менее проблемное try-finally он принципиально не разрешает, потому что, видите ли, есть RAII и всё что надо делать — можно сделать на нём.

Я бы согласился с его позицией, если бы он, аналогично современному managed/unmanaged коду, сделал метки "этот код написан в таком вот стиле, goto разрешить, сложные объекты и исключения запретить" (условно говоря). Но ведь он этого не сделал.

I>ИМХО — goto очень удобный инструмент при переходе внутри вложенных циклов. Ибо стандартно в C нет continue метка или break метка. А использовать флажки, как предлагалось выше — это кончено верх изящества ))))


Флажки нужны там, где код надо строго доказать.
Но я лично очень "за" помеченные циклы, аналогично перлу. Проблем от этого минимум, польза — огромная.
The God is real, unless declared integer.
Re[2]: Существуют ли задачи, где использование GOTO оправдан
От: Programador  
Дата: 01.08.07 09:40
Оценка:
Здравствуйте, ionicman, Вы писали:

I> А то началось — плохооо, когд не читаемый. Вот с Венгенрской нотацией код более читаемый — а че ее так мло используют? :D

Гдето я про это слышал. Тут ответ простой число скобок посчитать легче чем число пушей попов, хот и здесь после третьего уровня не совсем комфортно
Re[2]: Существуют ли задачи, где использование GOTO оправдан
От: NikeByNike Россия  
Дата: 01.08.07 09:43
Оценка:
Здравствуйте, ionicman, Вы писали:

I>Хорошая тема для обсуждения — это типа HolyWars-а почти

I>Я вот не понимал никогда, какого черта люди так говорят типа goto — плохой код и все такое.

Не, ты не понял Тут говорится что не готу плохой код, а готу — признак плохого кода. Это разные вещи.
Посмоти сколько готу встречается в stl или бусте
Нужно разобрать угил.
Re[3]: Существуют ли задачи, где использование GOTO оправдан
От: ionicman  
Дата: 01.08.07 09:45
Оценка: 1 (1)
N>Страуструп сильно непоследователен. goto он разрешил, у которого есть значительные проблемы в реализации (например, та же тема с конструкторами объектов, когда переход происходит в середину блока, или чуть попроще — при выходе по goto из блока) — тут уже проблемы с этим обсуждали. А вот значительно менее проблемное try-finally он принципиально не разрешает, потому что, видите ли, есть RAII и всё что надо делать — можно сделать на нём.
Ну во первых то что он был "непоследователен" :D И сделало язык C++ таким богатым
Во вторых действительно RAII вполне это решает, а вот использование таких хитрые решения с конструкторами объектов и goto — это отдельная тема, считаю что это действительно не шибко хорошее использвание для данного оператора.

N>Я бы согласился с его позицией, если бы он, аналогично современному managed/unmanaged коду, сделал метки "этот код написан в таком вот стиле, goto разрешить, сложные объекты и исключения запретить" (условно говоря). Но ведь он этого не сделал.

А зачем? есть goto нфрфду с исключениями — используй то что считаешь нужным. Стили и разрешения и запрещения на них — это придумали люди, использующие C++ ) Как он мог сказать за всех? У него есть рекомендации по написанию, есть еще тысячи вариантов как это делать. Выбери свое и придерживайся этого. Я за это его и уважаю что он не седлал так "Это неправильно — делайте так". За это мне и нравится C++ — свобода — ты сам Бог и Творец, и никто тебя не тыкает. Выберешь неудачную концепцию — виноват сам )

I>>ИМХО — goto очень удобный инструмент при переходе внутри вложенных циклов. Ибо стандартно в C нет continue метка или break метка. А использовать флажки, как предлагалось выше — это кончено верх изящества ))))


N>Флажки нужны там, где код надо строго доказать.

Они кроме того что замедляют исполнение абсолютно не нужныю Кроме того читать код с кучей симафоров гораздо хуже чем м темже goto. пример — для бэк трэкинга в 3 вложенных циклах при условии трекинга в пределах самого высокого требуется 2 флага — как Вам такое?
N>Но я лично очень "за" помеченные циклы, аналогично перлу. Проблем от этого минимум, польза — огромная.
Не, ну вариантов много. Я уже приводил пример выше про continue / break + label. Ну на самом деле goto не только в циклах удобен. Этим полностью решить все неудастся.
Re[10]: Существуют ли задачи, где использование GOTO оправда
От: Programador  
Дата: 01.08.07 09:52
Оценка:
Здравствуйте, NikeByNike, Вы писали:

NBN>Остальное вроде правильно, с поправкой на то, что состояние аргументов функции не изменится между вызовами конструктора и EstimateContour. Кстати, на таком подходе иногда удаётся ускорить функции в разы. Допустим, если есть проверка пересечения луча с большим количеством боксов — замена функции на функтор — даёт приличное ускорение.


Замена функции на функтор, тоесть сокрытие объекта, который модифицируется между вызовами? В принципе локальные классы уже появились. Если в функциях разрешить третий тип памяти, в дополнение к статической и авто, то можно унифицировать функции с классами. Ну и както еще поднапрячься и namespace туда
Re[3]: Существуют ли задачи, где использование GOTO оправдан
От: ionicman  
Дата: 01.08.07 10:00
Оценка:
NBN>Не, ты не понял Тут говорится что не готу плохой код, а готу — признак плохого кода. Это разные вещи.
NBN>Посмоти сколько готу встречается в stl или бусте

Ну вопервых кто те сказал что это истина в последних инситанциях? :D Достаточно удобные библиотеки предлагающие в обмен тормоза за удобство. Их пишут люди. А люди, как я уже писал, обычно придерживаются некоего стиля — вот и все. На самом деле goto достаточно редкий гость в программах, НО внекоторых ситуциях он гораздо более удобен как по скрости так и по прозрачности листинга. И он не является признаком "плохого" кода абсолютно. Вы же не называете признаком плохого кода функции или классы? А на них огого нагородить можно. Вы никогда не встречали исходники, создатели которых были больны ООП насмерть? Там в каждом месте по классику, пусть маленькому — но классику. Это ужас просто. Не читаемо и медленно вообще.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.