На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела:
1. Название темы - краткое описание кто/что против кого/чего
2. В первом сообщении - список параметров, по которым идет сравнение.
3. Старайтесь аргументировать свои высказывания. Фразы типа "Венда/Слюникс - ацтой" считаются флудом.
4. Давайте жить дружно и не доводить обсуждение до маразма и личных оскорблений.
Модераторы: Модераторы, Комодераторы
Страницы: (32) « Первая ... 26 27 [28] 29 30 ... Последняя »  ( Перейти к последнему сообщению )  
> goto vs break & continue , Кроха-сын пришел к отцу и спросила кроха: "goto - это хорошо?"
    Цитата Qraizer @
    Чтобы далеко не посылать.
    Первые два load-а читают посимвольно из-за того, что не знают, сколько там данных. Это также вызывает постоянные реаллокации приёмного буфера. Вторые два load-а читают скопом весь файл, заранее сконфигурировав приёмный буфер на требуемый размер. Что-то это мне напоминает... Ах да, std::vector<T> vs T*. Ну разве не прелесть.

    Да, надо свое мутить! :lol: Хотя есть задачи и по важнее. Например "окроссплатформить" чтение/запись в файл по позиционированию по off_t для x32/64.
      Ну и это я ещё спустил на тормозах const_cast<char*>(std::string::data())
        Цитата Wound @
        Он как раз все верно оценил, если я правильно понял что там произошло.
        Если бы он все верно оценил, он бы так не написал. Очевидно, что он думал, что деструкторы объектов на куче вызываются по тем же правилам, что и деструкторы объектов на стеке.
        Цитата Wound @
        Ну да, нахер юзать все эти RAII в плюсах. Вот дебилы, правда? че сложно написать delete ptr - где это нужно.
        Ну так они и пишут, в деструкторах оберток и кастомных делетерах unique_ptr.
        Цитата Wound @
        В Сяшке ровно тот же механизм, только вид с боку. Когда ты юзаешь мой любимый unique_ptr, то это полноценная RAII обертка, и она лишена практически всех недостатков. Например что будет у тебя, если во время выделения ресурса произойдет исключение? Будет очищать ресурс, который не существует?
        Нет в сяшке не тот же. Вызовуться только те scope(), которые успели отработать. Поведение scope(exit) в плане очистки ресурсов полностью совпадает с unique_ptr с кастомным деструктором. Похоже, ты не совсем понял оно работает. Вот посмотри очень короткий пример: https://run.dlang.io/is/7jJE7b
        Цитата Wound @
        Ну как не пишут, если пишут? Я ж даже ссылку привел на того, кто написал
        Он начинающий, очевидно. Представь себе, что новичок, заюзал shared_ptr для некоего обекта. Потом зачем-то в деструкторе какой-нибудь RAII-обертки сделал TTF_Quit, а позже в деструкторе объекта торчащем в shared_ptr вызвался TTF_CloseFont. Сегфолт. Похожим образом я много лет назад облажался с boost::asio. Объект сидящий в boost::shared_ptr (в те времена, еще не было std::shared_ptr) пережил другой объект, без которого он не мог нормально работать. Долго не мог понять что за говно, потом понял и больше так не делал. Ибо нефиг.
        Цитата Wound @
        сам по себе scope(exit) - Не влияет на порядок вызовов деструкторов, я нигде не утверждал что он влияет.
        Ты написал так:
        Цитата Wound @
        Ну и к слову, встречал что если класс в D создавать через new, то порядок вызовов с этим scope(exit) - уже не такой однозначный, а все из за GC, так что даже эта "плюшка" может запросто поломать программу.
        Я это понял так, что ты решил, что scope(exit) как-то влияет на это.
        Цитата Wound @
        Ага, с тебя взял пример. Ты же первый начал рассказывать как без него тяжко в плюсах жить
        Ну я не тащил сюда всякие странные багнутые куски кода. А так да, в C++ нет scope, но есть RAII, а в D есть и scope и RAII. :)
        Цитата Wound @
        Ты как раз таки все понял, просто тебе видимо потроллить хочеца. Я слышал в Java его частенько называют именно так. И название идет от полной конструкции. Finally не фигурирует сам по себе. Так что ты тоже ошибся выходит, если цеплятся к словам, как ты любишь
        Я не сразу понял. Когда я писал try/catch/finally я имел в виду совокупность всех возможных комбинаций и так же понял и твое try/catch/finally.
        Важно понимать, что scope(success)/scope(failure)/scope(exit) похожи на try/catch/finally, но отличия достаточно большие.
        Сообщение отредактировано: applegame -
          Цитата korvin @
          Обычно — нет. А финализаторы в Java давно признаны слишком проблемными. Поэтому ресурсы нужно использовать с try-with-resources.
          Да, наверное ты прав, обычно нет. Та же фигня и с деструкторами классов в D.
          Цитата D_KEY @
          А ты разве не такой пример привел?
          Нет не такой. Мне не нужен был объект владеющий ресурсом, мне нужен был сам ресурс. Под объектом в данном случае я подразумеваю не просто владение, но и предоставление интерфейса для работы с этим ресурсом. В моем случае, интерфейс был реализован через сишные вызовы внешних функций и, я не вижу никакого смысла писать обертку даже просто для владения. Результат запроса (указатель на PGresult), возвращаемый из сишной либы, никуда за пределы одной-единственной функции не попадает. Понимаешь? Этот PQClear встречается во всей моей обертке вокруг libpq ровно один раз, а именно в scope(exit) в одном из методов класса Connection. Ты предлагаешь городить RAII-обертку на случай: "а вдрух когда-нибудь мне понадобится работать с PGresult в нескольких разных местах"? Вот когда понадобится тогда и напишу, но скорее не RAII, а в функциональном стиле, так как считаю что писать RAII исключительно для владения - костыль. Но пока не понадобилось, и я более чем уверен что и не понадобится.
          Цитата D_KEY @
          Не согласен, он все равно лучше, чем явный defer/scope(exit).
          Классический пример скоупа - блокировка.
          Тут у тебя неверное сравнение. Ты же скрыл код самого std::lock_guard, в котором присутствует такой же mtx.unlock(). Тогда двай уж и scope(exit) вынесем в отдельную функцию:
          ExpandedWrap disabled
            {
              std::lock_guard lock(mtx);
              ...
            }

          против
          ExpandedWrap disabled
              locked(mtx, {
              ...
              });

          И знаешь чем второе лучше первого? Нет бесполезного и странно выглядящего для людей не знающих C++ объявления переменной lock, которая нигде потом явно не используется. То самое создание объекта исключительно ради владения ресурсом и без предоставления интерфейса работы с этим ресурсом. Самый что ни на есть настоящий костыль.
          Цитата D_KEY @
          Верно. И к этому примеру никаких претензий, это аналог RAII, хотя и с ограничениями.
          Но ты привел не этот код
          Вообще-то именно такой код я и привел. Более того, только в подобных случаях и уместен scope(exit). Если тебе приходится писать scope(exit) с одним и тем же кодом более одного раза - ты что-то делаешь не так.
          Цитата D_KEY @
          Можно согласиться, что defer/scope(exit) лучше finally(хотя и не сильно).
          Не знаю что за defer (Go?). А вот scope(...) довольно сильно отличается от finally как синтаксисом так и семантикой.
          Цитата D_KEY @
          Но еще лучше using/with/try-with-resources. Тем, что не нужно каждый раз указывать действие по освобождению.
          Ты просто читаешь тему по диагонали :) Я с самого начала говорил и несколько раз потом повторил, что scope(...) удобен для однократного использования и он умеет работать с чем угодно, а не только с ресурсами. Даже примеры счетчиков запросов приводил. А ты зациклился на ресурсах и DRY. Давай расциклись уже :D
          Если тебе нужно работать с ресурсом в разных местах, заверни scope(...) в отдельную функцию (получится тот же using/with/try-with-resources, только лучше, потому что гибче) или делай RAII.
          Цитата D_KEY @
          Но RAII выигрывает и у них. Хотя бы тем, что может быть точно так же использован для полей структуры/класса.
          Это как сказать, что вездеход лучше автомобиля, потому что вездеход может быть точно также использован для езды по болотам. :lol:
          Сообщение отредактировано: applegame -
            Цитата applegame @
            Не знаю что за defer (Go?)

            Да

            ExpandedWrap disabled
              f, err := os.Open("some/file")
              if err != nil { return err }
              defer f.Close()


            и ещё Zig, например

            ExpandedWrap disabled
              const std = @import("std");
               
              pub fn main() !void {
                  const file = try std.fs.cwd().openFile("does_not_exist/foo.txt", .{});
                  defer file.close();
                  try file.writeAll("all your codebase are belong to us\n");
              }
              Цитата Qraizer @
              И чем это будет отличаться от классического RAII? Ты ещё не забыл о главном преимуществе scope()ов, за которое радеешь?
              Тем, что написать такую обертку проще, чем RAII-класс. Ну и в случаях вроде лока мютексов еще и нет бесполезных объявлений переменных. Посмотри на свою иммитацию scope: scope1, scope2, scope3... - что это за мерзкие нумерованные переменные, которые нигде не задействованы? Вот где костыль-то.
              Цитата Qraizer @
              Вот. Собственно это и есть тот критерий, который оправдано можно закостылить scope()ом...
              Ага, "костыль", который выглядит чище, а работает не хуже. :D Костыль - это стрельба из пушки по воробьям.
              Цитата Qraizer @
              но вдруг и внезапно – скоуп может захотеть владеть разными ресурсами, в разном количестве и с разной стратегией владения.
              Если скоуп внезапно захочет чего-то сложного, то внезапно убирается scope(...) и делается та самая RAII-обертка. Но на моей практике такого никогда не было. Если я принял решение использовать scope(...), то в будущем так и не возникала необходимость его менять на RAII.
              Цитата Qraizer @
              Может быть иногда и не удобно, но всегда надёжно.
              Это называется оверинжиниринг, когда код усложняется "на всякий случай", даже когда вероятность возниконовения этого "всякого случая" в будущем близка к нулю. Я сам страдаю таким и раньше мне приходилось местами заставлять себя писать scope(exit) вместо RAII-обертки. Потому что объективная оценка показывала, что в данном случае "вдруг и внезапно скоуп никогда не захочет владеть разными ресурсами, в разном количестве и с разной стратегией владения." Сейчас уже почти привык не городить абстракции и обобщения там, где они вероятно не понадобятся никогда.
              Цитата Qraizer @
              Исполнение данных тобой инструкций – да, автоматическое. С этим и __attribute__((__cleanup__())) справляется. Интересно, почему его не включали в Стандарт C? Это же так удобно, по твоим словам.
              А по твоему удобнее эти goto? Да и cleanup гораздо примитивнее scope(exit).
              А так сишники народ странный, но думаю многим из них понравился бы scope(exit). А Стандарт это дело консервативное и тормозное. Сколько ждали появления в плюсах лямбд и auto?

              Добавлено
              Цитата korvin @
              и ещё Zig, например
              Да, вспомнил. Я пытался юзать Zig, но как-то не зашло. Слишком уж странные у них лозунги. ЕНМНИП, у них до сих пор нет лямбд.
              Сообщение отредактировано: applegame -
                Цитата applegame @
                ЕНМНИП, у них до сих пор нет лямбд.

                Так это приукрашенный C, откуда там лямбды? =)
                  Цитата korvin @
                  Так это приукрашенный C, откуда там лямбды? =)
                  Они там полиморфизьм обсуждают :) Почему бы и лямбды не сделать? Они вроде не противоречит их девизам.
                    Цитата applegame @
                    Этот PQClear встречается во всей моей обертке вокруг libpq ровно один раз, а именно в scope(exit) в одном из методов класса Connection.

                    Это было не очевидно из твоего кода. Если так, то спорить тут не о чем.

                    Цитата
                    Тогда двай уж и scope(exit) вынесем в отдельную функцию

                    Если мы это сделаем, то это будет уже другой подход. Понимаешь? :)

                    Цитата
                    И знаешь чем второе лучше первого?

                    Я достаточно подробно описал твое "второе" в предыдущем ответе тебе. И даже сказал, что не вижу в этом подходе ничего плохого, просто RAII более универсальный подход.

                    Цитата
                    Нет бесполезного и странно выглядящего для людей не знающих C++ объявления переменной lock, которая нигде потом явно не используется.

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

                    Зависит от того, к чему привык конкретный программист, который будет читать код. Вкусовщина.

                    Цитата
                    Самый что ни на есть настоящий костыль.

                    Я тебя уже просил привести свое определение термина "костыль". Никакой принципиальной разницы тут нет, поскольку и в случая RAII и в случае bracket pattern ты освободишь ресурс автоматически. В первом случае за счет "лишнего" объекта, во втором - за счет "лишних" вызова функции и лямбды.

                    Цитата
                    заверни scope(...) в отдельную функцию (получится тот же using/with/try-with-resources, только лучше, потому что гибче) или делай RAII.

                    Если ты используешь scope(exit) просто в реализации bracket pattern, то для работы с ресурсом ты используешь bracket pattern, а не scope(exit), понимаешь? scope(exit) у тебя просто часть реализации, там вооще мог быть try...catch, это не имеет принципиального значения ;)
                    Впрочем, я писал уже, что scope(exit) лучше finally, хотя и не принципиально.

                    Цитата
                    Цитата D_KEY @
                    Но RAII выигрывает и у них. Хотя бы тем, что может быть точно так же использован для полей структуры/класса.
                    Это как сказать, что вездеход лучше автомобиля, потому что вездеход может быть точно также использован для езды по болотам. :lol:

                    У автомобиля есть преимущества перед вездеходом, у bracket pattern перед RAII можешь такие указать?

                    Добавлено
                    Цитата korvin @
                    Цитата applegame @
                    Не знаю что за defer (Go?)

                    Да

                    ExpandedWrap disabled
                      f, err := os.Open("some/file")
                      if err != nil { return err }
                      defer f.Close()

                    Там, кстати, не собираются делать аналог try-with-resources? А with*-функции используют?
                    Сообщение отредактировано: D_KEY -
                      Цитата D_KEY @
                      Это было не очевидно из твоего кода. Если так, то спорить тут не о чем.
                      Я словами это говорил:
                      Цитата applegame @
                      Это освобождение в моей обертке фигурировало буквально внутри одной функции.
                      И потом еще неоднократно повторял. Но ты походу писатель а не читатель :) Впрочем, я тебя понимаю, кому охота читать портянки бессодержательных споров с Килей. :lol:
                      Цитата D_KEY @
                      Если мы это сделаем, то это будет уже другой подход. Понимаешь?
                      Конечно. Но ты же сам придумал это сравнение? Изначально-то речь шла о ситуации, когда у тебя выбор самому писать одноразовую RAII-обертку или воспользоваться одноразовым же scope(exit). А тут ты приводишь пример готовой RAII-обертки из стандартной либы да и еще подразумевая многократное ее применение.
                      Цитата D_KEY @
                      Зато есть странно выглядищий для людей не знакомым с паттерном вызов функции с передачей лямбды, хотя логично делать эти действия на том же уровне, поскольку контекст тот же и мы не специфицируем никакое поведение.
                      Лямбда подхватывает текущий контекст. Кроме того лямбда вообще может выглядеть просто как скоуп, который лочится. Например в D:
                      ExpandedWrap disabled
                        mutex.locked({
                           ...
                        });
                      Лично мне это видится более естественным, чем объявление переменной-гварда. Вызов функции любому программисту понятен: внутри что-то делается, по названию функции можно понять что именно делается. А в случае с объявлением переменной-гварда, нужно знать, что это RAII-объект. Потому что переменная объявлена и ничего с ней больше не происходит. Неплюсовик ожидает, что если переменную объявили, то значит ее собираются использовать, если же ее не используют, то это скорее всего ошибка (даже ворнинг такой есть unused variable). То бишь, в данном случае объявление переменной используют не по общепринятому назначению. Вот это я и называю костылем.
                      Цитата D_KEY @
                      Я тебя уже просил привести свое определение термина "костыль".
                      Нет, сначала ты приведи свое определение термина "определение термина". :)
                      Все субъективно, я привел свое мнение. А так вон фанаты сяшки или, прости господи, Zig будут называть любой твой RAII - вселенским злом и страшным костылем. И аргументы у них найдутся из серии: в этом вашем RAII-объекте непонятно что происходит, а в моей милой функции все явно написано. И хрен ты их переубедишь :)
                      Я высказал свое мнение и написал, что именно считаю костылем. Тебе это не показалось костылем - ну и флаг тебе в руки, что еще ты от меня хочешь? :D
                      Мы же тут просто мнениями обмениваемся и не ставим цели учить писать программы.
                      Цитата D_KEY @
                      Если ты используешь scope(exit) просто в реализации bracket pattern, то для работы с ресурсом ты используешь bracket pattern, а не scope(exit), понимаешь? scope(exit) у тебя просто часть реализации, там вооще мог быть try...catch, это не имеет принципиального значения
                      Впрочем, я писал уже, что scope(exit) лучше finally, хотя и не принципиально.
                      Да-да, так и есть. И scope(exit) очень удобно применять для реализации этого, хм паттерна, в языках, в которых существют исключения и ранний return.
                      До этого обсуждения ни разу не слышал, что это паттерн и что у него, оказывается, даже есть название. Хотя это похоже какой-то чисто хаскелевский мемасик.
                      Сообщение отредактировано: applegame -
                        Расслабтесь:
                        Прикреплённая картинка
                        Прикреплённая картинка
                          Цитата D_KEY @
                          Там, кстати, не собираются делать аналог try-with-resources?

                          Нет, и не думаю, что станут: try-with-resources работает только в рамках вызова процедуры и одного потока (одной горутины) — слишком узкоспециализированный механизм. Кроме того, try-with-resources в Java работает только если класс реализует
                          ExpandedWrap disabled
                            interface AutoCloseable {
                             
                                void close() throws Exception
                            }

                          а разные «ресурсы» могут иметь разные методы «захвата/освобождения» в соответствии с их семантикой: Open/Close, Lock/Unlock, Create/Delete и т.п. Либо заставлять всех использовать всегда один метод (Close, там или Release) — как-то тупо. Вводить в язык явное понятие ресурса с каким-нибудь спец-синтаксисом, типа помечать освобождающий метод каким-нибудь ключевым словом или спец-символом — ну хз. И это всё равно никак не поможет с разделяемыми ресурсами, например:

                          ExpandedWrap disabled
                            package main
                             
                            import (
                                "fmt"
                                "sync"
                                "time"
                            )
                             
                            const nWorkers = 5
                             
                            func main() {
                                fmt.Println("ok1:")
                                ok1()
                                fmt.Println("\nok2:")
                                ok2()
                                fmt.Println("\nnot ok:")
                                notOk()
                            }
                             
                            func ok1() {
                                var wg sync.WaitGroup
                                wg.Add(nWorkers) // acquire
                                for i := 0; i < nWorkers; i++ {
                                    go func(x int) {
                                        defer wg.Done() // release
                                        doSomeWork(x)
                                    }(i)
                                }
                                wg.Wait()
                            }
                             
                            func ok2() {
                                var wg sync.WaitGroup
                                for i := 0; i < nWorkers; i++ {
                                    wg.Add(1) // acquire
                                    go func(x int) {
                                        defer wg.Done() // release
                                        doSomeWork(x)
                                    }(i)
                                }
                                wg.Wait()
                            }
                             
                            func notOk() {
                                var wg sync.WaitGroup
                                for i := 0; i < nWorkers; i++ {
                                    go func(x int) {
                                        wg.Add(1) // acquire
                                        defer wg.Done() // release
                                        doSomeWork(x)
                                    }(i)
                                }
                                wg.Wait()
                            }
                             
                            func doSomeWork(x int) {
                                <-time.After(1 * time.Second)
                                fmt.Println("done #", x)
                            }

                          =>
                          ExpandedWrap disabled
                            ok1:
                            done # 2
                            done # 0
                            done # 4
                            done # 3
                            done # 1
                             
                            ok2:
                            done # 0
                            done # 2
                            done # 1
                            done # 3
                            done # 4
                             
                            not ok:
                             
                            Program exited.


                          try-with-resources тут никак не поможет, т.к. позволяет описать только вариант notOk.

                          А в JDK, ЕМНИП, у HttpURLConnection освобождающий метод называется disconnect, а не close и соответствено класс не реализует AutoCloseable и использовать его в try-with-resources нельзя :facepalm:

                          Цитата D_KEY @
                          А with*-функции используют?

                          Ну, некоторые используют, но callback-style не всем нравится.
                          Сообщение отредактировано: korvin -
                            Цитата applegame @
                            Если бы он все верно оценил, он бы так не написал. Очевидно, что он думал, что деструкторы объектов на куче вызываются по тем же правилам, что и деструкторы объектов на стеке.

                            Это тебе очевидно и синтетического примера в 5 строчек. Если бы все было просто как ты пишешь, баги делали бы только студенты по своему не знанию. На практике у него может быть довольно не примитивный код, чтоб верно оценить все ньюансы. Именно по этому писать руками дополнительную строчку - может являтся источником ошибок.
                            Ок, вот ты привел там функцию - с виду имитирующуюю RAII, в принципе такой вариант еще ладно, если знаешь что у тебя тут голый ресурс, и ты тут его же удаляешь - такое еще можно оправдать. Но ведь разные есть случаи, я понял бы если бы это была единная конструкция, хотя бы там через точку например. Но понимаешь ли, бывает так что пишешь new int, и тут же забываешь сделать delete, потому что это две конструкции, независимы друг от друга семантически. Так и тут.

                            Цитата applegame @
                            Ну так они и пишут, в деструкторах оберток и кастомных делетерах unique_ptr.

                            Это пишется в одной конструкции. Если было бы все так просто - все эти RAII нахер бы никому не упали. Какая проблема вызвать delete, после выделения ресурсов - да абсолютно никакой. И тем не менее в том же С++ утечек куча, из за того что люди полагаются на свои руки и память, а потом выхватывают утечки.

                            Цитата applegame @
                            Нет в сяшке не тот же. Вызовуться только те scope(), которые успели отработать. Поведение scope(exit) в плане очистки ресурсов полностью совпадает с unique_ptr с кастомным деструктором. Похоже, ты не совсем понял оно работает. Вот посмотри очень короткий пример: https://run.dlang.io/is/7jJE7b

                            Тут как бы и коню понятно что до второго scope оно не дойдет. Корректно ли отработает первый scope, если исключение произошло на этапе конструирования сложного объекта, вот в чем вопрос.

                            Цитата applegame @
                            Я это понял так, что ты решил, что scope(exit) как-то влияет на это.

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

                            Цитата applegame @
                            Ну я не тащил сюда всякие странные багнутые куски кода. А так да, в C++ нет scope, но есть RAII, а в D есть и scope и RAII.

                            Я его притащил - показать с какими проблемами можно столкнуться, полностью положившись на него. В С++ нет scope, потому что там нет GC, а в D есть GC, поэтому там и scope актуален. Для С++ этот scope(exit) - не более, чем синтаксический сахар.

                            Цитата applegame @
                            Я не сразу понял. Когда я писал try/catch/finally я имел в виду совокупность всех возможных комбинаций и так же понял и твое try/catch/finally.
                            Важно понимать, что scope(success)/scope(failure)/scope(exit) похожи на try/catch/finally, но отличия достаточно большие.

                            По сути все отличия сводятся к удобству использования. Не надо просто писать все эти try/catch/finally, но например тотже try-with-resources/using - уже куда более удобны этих конструкций try/catch/finally, и вполне себе могут даже потягаться со scope(exit).
                            Да и в такие языки любят тащить все попало, но scope(exit) - я там как то не встречал. Видимо даже там разрабы посчитали - что излишне вводить то, что уже есть в языке.
                              Цитата Wound @
                              Если бы все было просто как ты пишешь, баги делали бы только студенты по своему не знанию.
                              Такие ошибки и делают только студенты по своему незнанию.
                              Цитата Wound @
                              Ок, вот ты привел там функцию - с виду имитирующуюю RAII, в принципе такой вариант еще ладно, если знаешь что у тебя тут голый ресурс, и ты тут его же удаляешь - такое еще можно оправдать.
                              Ну так scope(...) и надо применять только в таких случаях. Я же говорил много раз.
                              Цитата Wound @
                              Но ведь разные есть случаи, я понял бы если бы это была единная конструкция, хотя бы там через точку например. Но понимаешь ли, бывает так что пишешь new int, и тут же забываешь сделать delete, потому что это две конструкции, независимы друг от друга семантически. Так и тут.
                              Я хз как такое можно забыть. Ты же вот прямо только что выделил память, и если ты не страдаешь склерозом, в голове автоматом возникает мысль: "надо освободить ресурс", и ты тут же пишешь scope(exit). С таким же успехом ты можешь забыть написать кастомный делетер в unique_ptr. Вот если у тебя такое встречается много раз, то уже становится неудобно, но в таких случаях и unique_ptr с кастомным делетером становится неудобным.
                              Цитата Wound @
                              Тут как бы и коню понятно что до второго scope оно не дойдет. Корректно ли отработает первый scope, если исключение произошло на этапе конструирования сложного объекта, вот в чем вопрос.
                              Конечно корректно, ведь конструирование происходит до scope(exit), соотвественно, если при конструировании произошло исключение, то scope(exit) не отработает. Разве это не очевидно?
                              Цитата Wound @
                              Имелось ввиду, что ты можешь положится на scope, ну раз оно от RAII вообще никак не отличается по твоим словам, а гдето выше другой чувак понадеется на полноценный деструктор, и это приведет к ошибке, как в примере по ссылке.
                              Он положился на scope и scope сделал ровно то, что он и ожидал, не больше не меньше. Его "обманул" GC, а не scope.
                              Цитата Wound @
                              Я его притащил - показать с какими проблемами можно столкнуться, полностью положившись на него.
                              Наоборот, он столкнулся с проблемой, потому что не полностью положился на scope, а понадеялся на деструктор. Если бы он полностью положился на scope и написал бы в нем TTF_CloseFont() и TTF_Quit(), то все бы работало без сегфолтов.
                              Цитата Wound @
                              В С++ нет scope, потому что там нет GC, а в D есть GC, поэтому там и scope актуален. Для С++ этот scope(exit) - не более, чем синтаксический сахар.
                              Неверно. scope(exit) и GC - вещи ортогональные. В моем же примере с PQClean, GC вообще никак не используется. И повторю еще раз: scope(...) может работать не только с ресурсами (в частности не только с памятью). И также повторю, что все RAII-парадигмы C++ работают и в D. Ну и какой это сахар, если для его реализации в плюсах надо маленькую либку написать, что и сделал Qraizer.
                              Цитата Wound @
                              но например тотже try-with-resources/using
                              Это сущности чуть более высокого уровня, чем scope(exit), но их можно реализовать при помощи scope(exit).
                              Цитата Wound @
                              Да и в такие языки любят тащить все попало, но scope(exit) - я там как то не встречал. Видимо даже там разрабы посчитали - что излишне вводить то, что уже есть в языке.
                              Разрабы тащат в языки все что им в голову взбредет, сам факт что разрабы что-то притащили или не притащили вообще не критерий. Тащат говно и наоборот хорошее не тащат сплошь и рядом.
                              Сообщение отредактировано: applegame -
                                Цитата applegame @
                                Такие ошибки и делают только студенты по своему незнанию.

                                Ну да, а остальные не делают никаких ошибок. :good: Я уже где то такое слышал.

                                Цитата applegame @
                                Ну так scope(...) и надо применять только в таких случаях. Я же говорил много раз.

                                Ну вообще мы объясняли человеку почему лучше в его случае избавится от goto, и обернуть ресурс в RAII обертку, приводили разные примеры, пришол ты и сказал - как хорошо что в D такого говна нет, а есть scope(exit). А теперь ты говоришь - что не говорил что он весь такой из себя ахереть какой.

                                Цитата applegame @
                                Я хз как такое можно забыть. Ты же вот прямо только что выделил память, и если ты не страдаешь склерозом, в голове автоматом возникает мысль: "надо освободить ресурс", и ты тут же пишешь scope(exit). С таким же успехом ты можешь забыть написать кастомный делетер в unique_ptr. Вот если у тебя такое встречается много раз, то уже становится неудобно, но в таких случаях и unique_ptr с кастомным делетером становится неудобным.

                                Когда работаешь с сырым указателем - очень часто забываешь написать delete. Тут примерно тоже самое - потому что это отдельная конструкция. С кастомным делитером - сразу видно будет что ресурс не освобождается, просто по самой конструкции. А этот scope(exit) - не обязательно можно написать сразу после выделения, его можно написать и в конце и в середине кода, уже после выделения памяти под ресурс. А раз так написать можно - значит будь уверен кто нибудь непременно так и напишет. Весь вопрос - как долго будут потом багу искать. Может быть сразу найдут, а может кто то неделю в отладчике проведет. Я вот именно это имею ввиду. Да ты можешь написать - вызывай сразу после выделения памяти под ресурс, но от этого возможность написать его где угодно никуда не девается.

                                Цитата applegame @
                                Конечно корректно, ведь конструирование происходит до scope(exit), соотвественно, если при конструировании произошло исключение, то scope(exit) не отработает. Разве это не очевидно?

                                Ну например там:
                                Цитата

                                Установили соединение
                                Открыли базу
                                Начали получать доступ к таблице - исключение

                                scope(exit){
                                Очистили ресурсы от таблицы
                                Закрыли Базу
                                Закрыли соединение
                                }

                                В итоге соединение и БД остались открытыми.

                                Цитата applegame @
                                Он положился на scope и scope сделал ровно то, что он и ожидал, не больше не меньше. Его "обманул" GC, а не scope.

                                Мы не знаем кто там кого обманул, вполне возможно что он написал все верно, а потом пришел вася, и вместо создания объекта на стеке как было, взял переделал создание объекта на куче.
                                Еще раз повторяю - там синтетический пример, обычно такие пишут, чтоб не захламлять лишними деталями и не сбивать людей с толку. Вот допустим у меня проект, хренова туча классов/кода летит какая то ошибка, я не буду все это выкладывать на форум, чтоб спросить что не так. Я возьму напишу минимальный, синтетический пример для воспроизведения проблемы, и выкачу его на форум, там будет 2 класса и три строчки с выводом в консоль, а в реале, может быть сотни классов и строк кода.

                                Цитата applegame @
                                Неверно. scope(exit) и GC - вещи ортогональные. В моем же примере с PQClean, GC вообще никак не используется. И повторю еще раз: scope(...) может работать не только с ресурсами (в частности не только с памятью). И также повторю, что все парадигмы C++, в том числе и RAII работают и в D. Ну и какой это сахар, если для его реализации в плюсах надо маленькую либку написать, что и сделал Qraizer.

                                Ну да, scope ортогонален GC примерно на столько же, на сколько и finally. Для его реализации достаточно написать unique_ptr, можно и класс написать. Qraizer тебе писал аналог в D, чтоб оно и выглядело и юзалось прям как один в один, максимально приближенно. Т.е. по сути он тебе этот сахар и реализовал на плюсах. А так это ничем не отличается от любого класса, в деструкторе которого выполняется то, что у тебя выполняется в теле scope. Потому как оно ровно так же - гарантированно выполняется в конце блока, устойчиво к исключениям, по сути как и finally. Так что scope(exit) - в плюсах это синтаксический сахар, не более. Были бы лямбды в плюсах более лаконичными, хотя бы похожи на делегаты в шарпах, то можно было бы переписать код с std::unique_ptr с кастомным делитером примерно вот так:
                                ExpandedWrap disabled
                                  auto resource = std::unique_ptr(new CResource(), (e) => {
                                    //! free resource.
                                    delete e;
                                  });

                                По сути в плюсах все к этому и сводится, если убрать весь этот синтаксический шлак по уточнению типов и указанию шаблонных параметров всяких.
                                Но на сколько я понимаю в плюсах такое написать нельзя из за скудного RTTI, поэтому и приходится чуть больше закорючек писать.

                                Ну и по описанию: https://tour.dlang.org/tour/en/gems/scope-guards
                                ExpandedWrap disabled
                                      // scope guards allow placing allocations
                                      // and their clean up code next to each
                                      // other
                                      import core.stdc.stdlib : free, malloc;
                                      int* p = cast(int*) malloc(int.sizeof);
                                      scope(exit) free(p);

                                Приводят ровно такой пример, который в С++ переписывается обычным unique_ptr, в примере free вызывается в scope(exit), в плюсах будет вызываться в кастомном делитере.

                                Цитата applegame @
                                Разрабы тащат в языки все что им в голову взбредет, сам факт что разрабы что-то притащили или не притащили вообще не критерий. Тащат говно и наоборот хорошее не тащат сплошь и рядом.

                                Ну в такие ЯП как JAVА/C# по моему тащат вообще все подряд, что можно затащить.
                                Сообщение отредактировано: Wound -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,1076 ]   [ 17 queries used ]   [ Generated: 7.05.24, 23:56 GMT ]