очередной круг спецзабега рсдн? okay
PD>Хм, а что тут неэффективно и неправильно ? PD>И в конце концов, неужели всеми уважаемый автор, признанный классик ИТ, будет писать в руководстве неэффективный и неправильный код. Зачем ему на позор себя выставлять ?
в той самой книге есть ошибки. порой нехорошие. кстати мыщъх их разбирал даже
PD>А то, что он демонстрационный — так и все, что там есть, демонстрационное. Там примеры того, как можно делать. А реальный код будет сложнее, конечно.
не буду комментировать
PD>И еще один вопрос, подумай. __finally в С появилось вместе с Win32. То есть это примерно так 1992-3 год. PD>Ява будет позже. C# — еще позже. А там эти конструкции штатные. Авторы Явы MS не очень любят, зачем же они тогда эту конструкцию в Яву ввели ?
в яве полный 0, но догадываюсь что, как и в шарпе, это из-за использования исключений вместо кодов возврата. что вкупе с архитектурой и высокой абстракцией просто необходимо
Здравствуйте, igna, Вы писали:
I>Это нормально, если для получения n-го ресурса нужно сначала получить (n-1)-ый для всех n в интервале от 2 до 5. Вложенность показывает, какой ресурс от какого зависит.
Я готов согласиться (с ограничениями), что это еще можно признать нормальным, когда речь идет о вложенности. А если не о вложенности ?
Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...
PD>>И всегда есть риск забыть про очистку, сделав где-то return в тот момент, когда абсолютно уверен, что отсюда надо выходить, а про очистку и не думаешь. И пишешь автоматически return — 1, и привет!
I>Ну наверное когда пишут функции, в которых логика управления ресурсами или еще что завязано на то, что выход из функции осуществляется одним единственным return (находящимся как правило в конце тела функции), использование return в других местах является табу.
Я бы не хотел дискутировать на эту тему, просто скажу — для меня это табу не является. все аргументы я слышал, но не считаю их убедительными.
>Тут не должно быть никакой автоматики. Так ведь кто-то и твое любимое третье решение Рихтера может испоганить, если "автоматически" запросит и освободит какой-либо новый ресурс не в соответствии с использованным там паттерном.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, о_О, Вы писали:
PD>>>Естественно, ничего личного.
о_О>>ололо павел, я то думал вы Капитан Политкорректность, или хотя бы додумаетесь, в вашем-то возрасте, подобное не комментировать...
PD>Просто тут есть личности, которые могут все принять на свой счет, ну я на всякий случай из извинился
особенно здорово если учитывать, что мой пост был в вашу пользу
Здравствуйте, о_О, Вы писали:
о_О>в той самой книге есть ошибки. порой нехорошие. кстати мыщъх их разбирал даже
От ошибок никто не застрахован, но одно дело — ошибка, а другое — предлагать порочное решение.
о_О>в яве полный 0, но догадываюсь что, как и в шарпе, это из-за использования исключений вместо кодов возврата. что вкупе с архитектурой и высокой абстракцией просто необходимо
Если мы начнем еще дискуссию на тему "исключения против кодов возврата" — кончим ее не скоро. Предлагаю не начинать
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, о_О, Вы писали:
о_О>>goto. и никакого SEH. вы против goto? вы просто не умеете его готовить
PD>С goto будут те же проблемы. return, break, continue, goto...
PD>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.
вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если"
иногда на обдумывание уходит 90% времени, а на написание 10%. зато потом из проекта в проект банальный копи-паст
PD>>Просто тут есть личности, которые могут все принять на свой счет, ну я на всякий случай из извинился
о_О>особенно здорово если учитывать, что мой пост был в вашу пользу
Здравствуйте, о_О, Вы писали:
PD>>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.
о_О>вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если" о_О>иногда на обдумывание уходит 90% времени, а на написание 10%.
Совершенно верно.
>зато потом из проекта в проект банальный копи-паст
Именно. Но боюсь, за копи-паст на тебя сейчас набросятся
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Если мы начнем еще дискуссию на тему "исключения против кодов возврата" — кончим ее не скоро. Предлагаю не начинать
Здравствуйте, о_О, Вы писали:
о_О>кстати вспомнил, что в яве goto и нет
У меня к goto сложное отношение.
Привык к нему за фортрановские годы. А потом пересел на Паскаль. А там он есть, но использование его — дурной тон вроде. А я привык. Надо отвыкать. И отвык. Через несколько лет понял, что мне его и употреблять не хочется.
Но принципиальным противником его я не был и не являюсь. И вполне уверен в том, что из двойного цикла выбраться наружу гораздо проще и понятнее с goto, чем с помощью дополнительных переменных и проверок. Но, пожалуй, напишу все же без него. Террор среды
KISS
Кстати. Во времена Win16 попался мне как-то исходник DefWindowProc, ее тогда опубликовали. Там goto было не мало, но один ме очень понравился
goto ICantBelieveThatIUsedGoToStatement;
Вот goto назад — это ИМХО действительно зло. goto назад — это цикл, а раз так, будьте добры оператор цикла и используйте.
Здравствуйте, Pavel Dvorkin, Вы писали:
>>зато потом из проекта в проект банальный копи-паст
PD>Именно. Но боюсь, за копи-паст на тебя сейчас набросятся
как набросятся так и отбросятся. если моё первое сообщение неделю назад, это не значит ничего
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>У меня к goto сложное отношение.
PD>Привык к нему за фортрановские годы. А потом пересел на Паскаль. А там он есть, но использование его — дурной тон вроде. А я привык. Надо отвыкать. И отвык. Через несколько лет понял, что мне его и употреблять не хочется.
PD>Но принципиальным противником его я не был и не являюсь. И вполне уверен в том, что из двойного цикла выбраться наружу гораздо проще и понятнее с goto, чем с помощью дополнительных переменных и проверок. Но, пожалуй, напишу все же без него. Террор среды
я соглашусь, что goto надо избегать, но не запрещать. более того, применять его сложно. особенно НЕ в ущерб чего-либо
PD>Вот goto назад — это ИМХО действительно зло. goto назад — это цикл, а раз так, будьте добры оператор цикла и используйте.
а что скажете вот о таком? как тут без goto?
uint TTabber::_NewItemId() const
{
uint res;
again:
res = _ItemIdGen();
for (SizeT n = 0; n < _ItemList.size(); n++)
if (res == _ItemList[n]->ID) goto again;
return res;
}
//при внимательном прочтении вроде всё и так ясно
о_О>а что скажете вот о таком? как тут без goto? о_О>
о_О>uint TTabber::_NewItemId() const
о_О>{
о_О> uint res;
о_О> again:
о_О> res = _ItemIdGen();
о_О> for (SizeT n = 0; n < _ItemList.size(); n++)
о_О> if (res == _ItemList[n]->ID) goto again;
о_О> return res;
о_О>}
о_О>//при внимательном прочтении вроде всё и так ясно
о_О>
Примерно так. Естественно, за возможное зацикливание я не отвечаю.
bool bNotFound = false;// на чистом С замени на char = 0;while(!bNotFound)
{
SizeT size = _ItemList.size(); // может, вынести из цикла, если размер не меняется
res = _ItemIdGen();
bNotFound = false;
for (SizeT n = 0; n < size ;n++)
if (res == _ItemList[n]->ID)
break;
if(n == size)
bNotFound = true;
}
Здравствуйте, blackhearted, Вы писали:
K>>4) Используете garbage collector? Но он же точным быть не может? А производительность? А кроссплатформенность? B>А это тут при чём? Что за точность?
Про точность я ошибался. Для C++ существуют точные сборщики мусора (хотя для C++ сборка мусора — вещь все равно условная, так как она принципиально не может быть эффективной).
B>Где вам не хватает перформанса? Вы покажите.
Просто хотелось узнать, как народ делает в своих программах, чтобы сделать выводы. А то вдруг я чего-то не знал? Пока что ничего нового не предложили.
Здравствуйте, gegMOPO4, Вы писали:
K>>Как вы реально работаете с памятью в C++? MOP>А вы как реально с числами работаете? Складываете их, отнимаете, умножаете или делите? Зависит от задачи.
Похоже, для C++-программиста это естественный ответ. Программисты на большинстве других языков так не думают.
В идеале, по крайней мере, в 99% выделение памяти вполне даже может быть полностью автоматическим, без всякой необходимости со стороны программиста думать о том, где как что выделяется и как отслеживается. Оставшийся 1% остается на случаи, когда предъявляются повышенные требования к производительности.
Так что ничего нормального в такой ситуации, когда программист "в зависимости от задачи" каждый раз отдельно решает, как управлять памятью, нет.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Здравствуйте, igna, Вы писали:
I>>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>>Часто использую __try — __finally PD>Просто я порой пишу на С
Это ты, конечно, молодец, но вопрос был "Как вы реально работаете с памятью в C++?"
Причем тут техники Си
PD>Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...
Потом ты берешь и проверяешь наличие всех необходимых ресурсов и выполняешь работу только при их наличии. А потом независимо от того, выполнялась ли работа, освобождаешь полученные ресурсы. По крайней мере нестандартные конструкции использовать не надо, хотя проверки — да, останутся:
if (hdc && hPen && hBmp && hFile) {
. . .
}
if (hFile)
CloseHandle(hFile);
if (hBmp)
CloseHandle(hBmp);
if (hPen)
CloseHandle(hPen);
if (hdc)
CloseHandle(hFile);
А это есть перенесение логики, которую может обработать компилятор, в рантайм. На мой взгляд лучше уж отступы или goto:
if (!(hdc = GetDC(...)))
goto end;
if (!(hPen = CreatePen(...)))
goto end_hdc;
if (!(hBmp = LoadBitmap(...)))
goto end_hPen;
if (!(hFile = CreateFile(...)))
goto end_hBmp;
. . .
end_hFile:
CloseHandle(hFile);
end_hBmp:
CloseHandle(hBmp);
end_hPen:
CloseHandle(hPen);
end_hdc:
CloseHandle(hFile);
end:
Но тут конечно есть свои недостатки по сравнению с __try/__finally, поэтому я возвращаю дискуссию к первому варианту (с проверками и без goto). Он то чем хуже?
PD>Я бы не хотел дискутировать на эту тему, просто скажу — для меня это табу не является. все аргументы я слышал, но не считаю их убедительными.
Хорошо. На всякий случай все же замечу, что я не про запрет на несколько операторов return в общем случае, а про конкретную функцию, логика которой требует, чтобы return находился в одном месте.
PD>А это невозможно, в том то и дело. PD>Новый ресурс ? Пожалуйста
PD>>Тасуй эти строчки как хочешь — они независимы друг от друга. Стоять рядом им совсем не обязательно. А теперь представь себе, что вначале берется HDC, потом при каких-то услоовиях создается перо (а может, и не создается), потом в каком-то другом месте загружается битовая карта (а как там с пером — а бог его знает), потом где-то файл открывается, а может, и нет, потом все это в цикле оказывается, кроме GetDC, и при разных проходах цикла действия раздичны, а потом...
I>Потом ты берешь и проверяешь наличие всех необходимых ресурсов и выполняешь работу только при их наличии.
Ресурсы эти независимы, и работа с каждым ресурсом не обязательно зависит от успешности создания остальных. Мне тут все равно.
>А потом независимо от того, выполнялась ли работа, освобождаешь полученные ресурсы. По крайней мере нестандартные конструкции использовать не надо, хотя проверки — да, останутся:
I>
Да, только не надо WIN API CloseHandle применять к hBmp . Извини за занудство.
I> А это есть перенесение логики, которую может обработать компилятор, в рантайм. На мой взгляд лучше уж отступы или goto:
I>
Ты меня не понял. Неудача в открытии каког-то ресурса в моем примере — не всегда основание для прекращения работы. Может да, а может и нет. Здесь нет вложенного доступа к ресурсам. Если я не смогу загрузить битмэп, то открою файл. А если смогу ее загрузить — может, тоже открою файл. Никаких предположений делать не надо о том, когда я продолжу или выйду и почему.
I>Но тут конечно есть свои недостатки по сравнению с __try/__finally, поэтому я возвращаю дискуссию к первому варианту (с проверками и без goto). Он то чем хуже?
А просто тем, что я вскоре потеряю представление, что и когда я должен закрывать
HDC получили
перо не создалось
битовую карту не создали
Может, надо выйти, а может, нет. Если надо — что закрывать ?
А если нет открываем файл. Успешно
а в файле информация о битовой карте. Откроем-ка заново. Успешно
И тут выяснилось, что карта не та. Может, надо выйти, а может, нет. Если да — что закрывать ?
А если нет — надо карту закрыть. И вновь попробовать создать перо
И вот сюда пришли. И что тут закрывать и что нет ? Я уже совершенно не понимаю, что я открыл и что нет, и что надо закрывать, а что нет.
I>Хорошо. На всякий случай все же замечу, что я не про запрет на несколько операторов return в общем случае, а про конкретную функцию, логика которой требует, чтобы return находился в одном месте.
А когда логика это требует и когда не требует ?
PD>>А это невозможно, в том то и дело. PD>>Новый ресурс ? Пожалуйста
I>
I>Почему же невозможно? Вот именно вместо освобождения ресурса в __finally освободить его где-то в другом месте.
На здоровье. Только освобождать надо так
DeleteResource(hRsrc);
hRscrc = 0;
В Delphi есть специальная функция FreeAndNil.
Вообще у меня правило такое. Рабочие переменные (те, которые на 2-3 строчки нужны) можно бросить после использования в неопределенном состоянии. Для чего-то более серьезного состояние должно всегда быть определенным. Если это дескриптор — пусть он будет !=0 пока он валиден, а удалили объект — присвойте ему 0. Указатель — аналогично.
Здравствуйте, о_О, Вы писали:
о_О>>>goto. и никакого SEH. вы против goto? вы просто не умеете его готовить :xz:
PD>>С goto будут те же проблемы. return, break, continue, goto...
PD>>А готовить goto я умею. Я лет 10 писал на Фортране-4, в котором не было цикла, кроме как с индексом. Так что циклов с помощью GOTO я немало написал.
о_О>вот это как раз и есть проявление профессиональных качеств/навыков — избегать подобных "а что если" о_О>иногда на обдумывание уходит 90% времени, а на написание 10%. зато потом из проекта в проект банальный копи-паст :xz:
Ну банального копи-паста по любому надо избегать. Хотя между проектами, наверно, пофиг. Вот в одном файле — может быть критичным. У нас как-то из-за такого патч наложился на другой участок кода (с fuzz'ом, но без полного отказа), последствия поймали только на тестировании вживую.
Но я не о том, а о goto. Собственно, начав с Фортрана, я тоже его люблю нежной любовью (во всех смыслах), причём даже такие суперхитрые варианты, как назначенный goto. Но с другой стороны — двухлетний опыт Erlang'а и шестилетний — Python'а приучил обходиться без него:) и надо заметить — это в принципе не сложно. Вопрос только в эффективности. В некоторых случаях (на процедурных языках без обработки исключений) приходилось строить вместо одной функции две — в первой создаётся набор переменных, передаётся во вторую, которая делает return по каждому чиху, затем в первой независимо от возвращённого значения делается зачистка и только тогда управление возвращается вызвавшему. Не скажу, что это выглядело симпатично — скорее, это было меньшее из всех возможных зол. Тогда я однозначно предпочёл бы goto, если бы он был доступен.