LINUX.ORG.RU

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

 


0

0

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

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

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

★★★★★

Проблема высосана из пальца. gcc, например, вообще не откомпилирует такой код.

Reset ★★★★★
()

>лучше всего совсем избегать переходов goto в программах на С++
Что верно, то верно

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

>>лучше всего совсем избегать переходов goto в программах на С++

>Что верно, то верно

А если у тебя, к примеру, пять вложенных for и надо из внутреннего выйти наружу? Четыре раза "if (leavin_all_loops) break;"?

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

>А если у тебя, к примеру, пять вложенных for и надо из внутреннего выйти наружу? Четыре раза "if (leavin_all_loops) break;"?

можно флаг завести, и назвать, например ToQuit

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

>А если у тебя, к примеру, пять вложенных for и надо из внутреннего выйти наружу?

Эксепцию кидай, эксепцию.

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

>for (i = 0; i <= 100 && !ToQuit; i++)

Оверхэд, однако.
Вот пример, как я считаю, оправданного применения готу:

Obj found;
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
for (int k = 0; k < 100; k++)
for (int l = 0; l < 100; l++)
for (int m = 0; m < 100; m++)
{
if (found=some(i,j,k,l,m))
{
goto leave_i_loop;
}
}
leave_i_loop:
do_smth_with(found);

Избавиться от goto тут можно, но ценой неслабого оверхэда (миллионы лишних проверок флага).
Печально, что многие программисты относятся к этому оператору с суеверным страхом (напишешь "goto" и за тобой придёт бабай! Буууу!).

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

>Эксепцию кидай, эксепцию.

Вариант, конечно. Но код длиннее и читаемость страдает не меньше ("throw" == "алярм!ошибка!", отвыкнуть от этого рефлекса трудно и не нужно).

legolegs ★★★★★
() автор топика

Я бы сильно удивился если бы он вызывался.

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

>> Эксепцию кидай, эксепцию.
> Вариант, конечно. Но код длиннее и читаемость страдает не меньше


В отличие от goto, с exception можно перейти только дальше по коду, но не в начало. И это значительно упрощает восприятие.

> ("throw" == "алярм!ошибка!", отвыкнуть от этого рефлекса трудно и не нужно).


Плохой рефлекс. Искореняй.

gaa ★★
()

>лучше всего совсем избегать переходов goto

fxd

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

>В отличие от goto, с exception можно перейти только дальше по коду, но не в начало. И это значительно упрощает восприятие.

Всё равно не считаю применение исключений "в мирных целях" правильным.

PS глянул сейчас черновик стандарта c++0x - ни слова про апргрейд break :( А хорошо бы иметь бряк "жава-стайл" ("break <число циклов>") или "break <метка ниже>".

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

>Всё равно не считаю применение исключений "в мирных целях" правильным.

Печально, что многие программисты относятся к применению исключений "в мирных целях" с суеверным страхом (напишешь exception и за тобой придёт бабай! Буууу!)

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

> Печально, что многие программисты относятся к применению исключений "в мирных целях" с суеверным страхом (напишешь exception и за тобой придёт бабай! Буууу!)

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

// wbr

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

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

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

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

вы хотите сказать, что исключение для выхода из цикла лучше чем goto? сам не использую goto, но использовать исключения для таких целей - извращение

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

Я тут поразмыслил и пришёл к выводу, что goto в приведённой мной ситуации с циклами много лучше, чем throw. goto передаёт управление и вверх и вниз, но в пределах данной функции. А throw передаёт управление туда, где есть подходящий catch -- т.е. малейшая ошибка в генерации исключения - и мы функцией выше или вообще в main. Не, goto надёжней.

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

Тоже плюсую. А если уж так хочется сделать много вложенных циклов и выходить из всех разом - выносим в отдельную функцию и выходим стандартным return'ом. При этом хотя бы не получается спагетти из goto =).

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

>То у тебя проблемы и так, без всяких goto.

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

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

> С чего бы, почтеннейший? форов у меня всегда столько, сколько требует алгоритм решения задачи.

и все они в теле main()-а?

// wbr

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

>вы хотите сказать, что исключение для выхода из цикла лучше чем goto?

Да. Во всяком случае легче читается, как по мне.

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

> С чего бы, почтеннейший? форов у меня всегда столько, сколько требует алгоритм решения задачи.

значит вы ленитесь выносить логические части кода в отдельные функции

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

> Да. Во всяком случае легче читается, как по мне.

мне такого не понять

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

> С чего бы, почтеннейший? форов у меня всегда столько, сколько требует алгоритм решения задачи.

Хороший алгоритм, бесспорно. O(n^5) --- это вам не какой-нибудь вялый qsort! :)

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

>выносим в отдельную функцию

Здраво в целом, но не всегда подходит. Например, если надо знать после выхода значения всех счётиков. Не по ссылке же их передавать.

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

> Здраво в целом, но не всегда подходит. Например, если надо знать после выхода значения всех счётиков. Не по ссылке же их передавать.

зачем их надо знать?

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

>и все они в теле main()-а?

Разумеется нет. В main вообще циклов нет :)

>значит вы ленитесь выносить логические части кода в отдельные функции

Надеюсь, вы не предлагаете делать функцию, которая будет сто раз дёргать функцию, которая сто раз будет дёргать функцию...

>Хороший алгоритм, бесспорно. O(n^5) --- это вам не какой-нибудь вялый qsort! :)

При чём здесь qsort? Если у меня есть сто островов Буянов, на каждом растёт сто дубов, на которых по сто сундуков, в которых по сто зайцев, в каждом зайце по сто уток, то задача убийста Кащея имеет сложность O(n^5) и хорошо ещё, если иголка в утке одна.

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

> Надеюсь, вы не предлагаете делать функцию, которая будет сто раз дёргать функцию, которая сто раз будет дёргать функцию...

почитайте, что такое inline

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


а когда вам надо искать не в "сто островах Буянов", а в одном вы радостно пишите очередные n-цать вложенных циклов?

> иголка в утке одна


садизм то какой

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

> Если у меня есть сто островов Буянов, на каждом растёт сто дубов, на которых по сто сундуков, в которых по сто зайцев, в каждом зайце по сто уток, то задача убийста Кащея имеет сложность O(n^5) и хорошо ещё, если иголка в утке одна.

И всё это записано в одной функции вложенными циклами с лапшой из goto? Мсье знает толк в извращениях.

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

>а когда вам надо искать не в "сто островах Буянов", а в одном вы радостно пишите очередные n-цать вложенных циклов?

Во-первых, n-цать минус один. А во вторых, когда мне понадобится, тогда и вынесу нужные в двух местах циклы в функции. У приличных программиств, занете-ли, есть план и лишних сущностей там быть не должно. Если я буду _ожидать_, что в будущем ТЗ изменится/дополнится и пользователь захочет искать по одному острову или сундуку, то спроектирую программу соответствующе (с функциями и всем прочим). Если ТЗ окончательное - то выносить каждый цикл в отдельную функцию я не намерен, ибо так можно возиться до бесконечности, превращая программу в миллиард функций в одну строчку каждая.

И в любом случае, выход из вложенных циклов через флаг выхода - трудночитаемо и неэффективно.

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

>И всё это записано в одной функции вложенными циклами с лапшой из goto? Мсье знает толк в извращениях.

Я этот код привёл выше. goto только один.

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

Ничего печального в этом нет. Исключения советую использовать как раз таки для "исключительных" ситуаций - "аларм, ошибка". Советуют по очень простой причине - исключение - это медленно. Во всяком случае в Java. Если интересно просто протестируй. Напиши код где постоянно бросается исключение или вместо него используется более сложный алгоритм.

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

> У приличных программиств, занете-ли, есть план

звучит двусмысленно

> лишних сущностей там быть не должно.


с каких пор фунция стала сущностью

> если я буду _ожидать_, что в будущем ТЗ изменится/дополнится и пользователь захочет искать по одному острову или сундуку, то спроектирую программу соответствующе (с функциями и всем прочим)


так бы и сказали - пишите одноразовые заказы, исправлять/дополнять никто не будет

> Если ТЗ окончательное - то выносить каждый цикл в отдельную функцию я не намерен, ибо так можно возиться до бесконечности


зачем каждый цикл, вы вроде про пять вложенных писали

> превращая программу в миллиард функций в одну строчку каждая.


что же вы такое глобальное пишите?

> И в любом случае, выход из вложенных циклов через флаг выхода - трудночитаемо и неэффективно.


в любом случае много вложенных циклов - "трудночитаемо и неэффективно"

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

>Если я буду _ожидать_, что в будущем ТЗ изменится/дополнится и пользователь захочет искать по одному острову или сундуку, то спроектирую программу соответствующе (с функциями и всем прочим). Если ТЗ окончательное - то выносить каждый цикл в отдельную функцию я не намерен, ибо так можно возиться до бесконечности, превращая программу в миллиард функций в одну строчку каждая.

Юношеский неистребимый оптимизм и максимализм? Ничего, это обычно проходит с первым-вторым серьёзным проектом ;)

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

>А с одного обычно и начинается :)

Очень хорошо. Где, по вашему, тут можно продолжить и как бы вы решили эту проблему?

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

> Избавиться от goto тут можно, но ценой неслабого оверхэда (миллионы лишних проверок флага).

Сделай break косному мышлению - если оверхед не запарит.

if (found=some(i,j,k,l,m)) {

i = 100; j = 100; k = 100; l = 100; m = 100;

break;

}

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

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

>i = 100; j = 100; k = 100; l = 100; m = 100;

где-то выше по тексту была ремарка что значения iklmn нужны после выхода из циклов. Так что не вполне корректное предложение.

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

> где-то выше по тексту была ремарка что значения iklmn нужны после выхода из циклов. Так что не вполне корректное предложение.

А сохранить их не судьба? В любом случае лучше заводить флаг исключительного события, которое надо обработать - и проанализировать сохраненные состояния.

Хотя в любом случае, C++ это конструктор из которого можно лепить что больше нравится.

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

>Например, если надо знать после выхода значения всех счётиков

Ну, блин, до такого же извращения как goto ты додумался? Почему не додумался сохранить значения в векторе или массиве или чём-то ещё?

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

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

Передать их параметрами по ссылке?

MYMUR ★★★★
()

Помнится, когда-то Дейкстра красиво выразился, что если человек не может выразить свои мысли без goto, то он, образно, ССЗБ.

trapezoid
()
Ответ на: комментарий от Demon37

А еще можно дрочить вприсядку. Может стоит оставить религиозный фанатизим по-поводу goto, а просто его использовать и не изобретать различные костыли лишь бы без goto ? Ты считал сколько раз встречается goto в больших проектах типа исходники ядра линукса?

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

> Ты считал сколько раз встречается goto в больших проектах типа исходники ядра линукса?

Тебе описать, в каком именно виде они там используются? Как раз в таком, в котором можно выразить try-catch-finally на си.

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

>А еще можно дрочить вприсядку. Может стоит оставить религиозный фанатизим по-поводу goto, а просто его использовать и не изобретать различные костыли лишь бы без goto ?

Использовать goto -- это и есть "дрочить вприсядку". Если костылями называть "неизящные решения", то использование goto в С++ -- костыль.

P.S. Никакого фанатизма, тем более религиозного. Просто считаю использование goto -- некрасивым, "топорным" решением. Таково моё мнение.

Demon37 ★★★★
()

>лучше всего совсем избегать переходов goto в программах

Вот так оно звучит лучше.

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

> Использовать goto -- это и есть "дрочить вприсядку"ъ

тогда писать на ассемблере - это "дрочить вприсядку" и быстро бегать при этом :)

если goto надо - чего бы и не поставить, но практика показывает, что реально таких ситуаций практически нет, примеры приводимые защитниками goto абсолютно не подходят - т.к. доказывают лишь их неспособность/нежелание правильно организовать структуру кода( вроде 5 вложенных циклов где на выходе надо знать ijklm - со стороны на такой код без слез не взглянешь, а то что переменная цикла будет использоваться после его завершения - это вообще "сказка" для того кто будет дебагить чужой код )

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