1. C++ / Говнокод #14414

    +19

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    template<class T>
    class smartest_ptr
    {
    std::unique_ptr<T> m_p;
    std::array<char, sizeof(T)> m_data; // массив размером с объект
    public:
    void New() {m_p = new(&m_data) T();}
    operator ->() {return m_p;}
    };
    
    // никакого выделения памяти из кучи!
    smartest_ptr<CFoo> pFoo; // типа nullptr
    // pFoo->Method(); - нельзя, nullptr
    pFoo.New();
    pFoo->FooMethod();
    pFoo->AnotherMeth();

    -- Чип и ДейлКрестовики спешат на помощь тем у кого медленная куча.
    -- Откуда спешат?
    -- Оттуда.

    Запостил: LispGovno, 26 Января 2014

    Комментарии (47) RSS

    • Умнейший указатель... Нет... Не так...
      О мудрейший и могущественнейший из указателей!
      Ответить
    • std::unique_ptr<T> m_p;
      m_p = new(&m_data) T();

      разве так можно? У unique_ptr выпили же operator =
      Ответить
      • Да, ты прав. Надо reset() вместо =.

        P.S. А ведь unique_ptr потом сделает этому буферу delete... И кровь-кишки-распидорасило...
        Ответить
      • > разве так можно?
        Я подозреваю, что это концепт, который спасёт мир от медленых аллокаций памяти в крестах
        Ответить
    • - Но чем это отличается от локальной переменной, объявленной внутри какого-нибудь блока?
      - Это же заумный указатель! Ты ничего не понимаешь в крестах, нуб!
      Ответить
      • Ну и чтобы от него была хоть какая-то польза, имхо, надо переделать метод new вот так:
        template <class... A> void New(A && ... args) {
            m_p = new (&m_data) T(std::forward<A>(args)...);
        }
        Ответить
    • Вот и меня затянуло в крестоблядскую трясину :(
      template <class T> class smartester_ptr {
      public:
          template <class... A> void New(A && ... args) {
              if (ptr)
                  ptr.reset();
              ptr.reset(new (&buf) T(std::forward<A>(args)...));
          }
          void Delete() {
              ptr.reset();
          }
          operator bool() {
              return (bool)ptr;
          }
          T & operator * () {
              return *ptr;
          }
          T * operator -> () {
              return ptr.get();
          }
      private:
          struct destroyer {
              void operator() (T *p) {
                  p->~T();
              }
          };
          typedef std::unique_ptr<T, destroyer> dumb_ptr;
          dumb_ptr ptr;
          char buf[sizeof(T)];
      };
      http://ideone.com/WxB4kN
      Ответить
      • > dumb_ptr
        На фоне мудрейшего указателя
        > smartester_ptr
        уникью_птр смотрится как тупой.
        Ответить
      • Нафига, когда можно было обычный голый указатель юзать вместо std::unique_ptr?
        Ответить
        • Лень писать пачку deleted методов, чтобы объект не копировался, деструктор и т.п. Банальная лень ;)

          Ниже chtulhu написал вариант без std::unique_ptr.
          Ответить
    • http://ideone.com/XDYxEP
      Ответить
      • Ну это прям smartestest_ptr :)
        Ответить
      • Посмотрел на твой код и пришла в голову мысль написать мудрейший из мудрейших указателей, которому можно присваивать из внешних указателей, а не только то, что выделено из буфера.
        Ответить
    • Реквестирую smartass_ptr.
      Ответить
    • the_smartest_ptr
      Ответить
    • КРЕСТОБЛЯДСКОЕ КРЕСТОБЛЯДСТВО КРЕСТОБЛЯДЕЙ КРЕСТОБЛЯДСКОГО КРЕСТОЯЗЫКА ЗАКРЕСТОБЛЯДНУЛОСЬ ЗА КРЕСТОБЛЯДСКУЮ КРЕСТОГРАНЬ
      Ответить
    • Что это за говно?
      Зачем оно надо?
      Какую проблему решает?
      Нихера не пойму.

      Целый крестофорум наркоманов дни напролёт только тем и занимается что придумывает какие-то замысловатые конструкции ебанутее прежних...
      Ответить
      • Проблема (предположительно): есть время, но не нехуй делать есть объект с дорогим конструктором и нужно инициализировать его только по необходимости, но при этом не выделяя под него память в куче (т.к. такты на аллокацию).

        Решение: запилить на стеке место под объект, и отложить инициализацию до вызова New().
        Ответить
      • >Какую проблему решает?
        наличие свободного времени :)
        Ответить
        • на отладку
          Ответить
          • А чего тут отлаживать?
            Ответить
            • порчи памяти, забытые деструкторы, да что угодно. этож гейдев
              в нем сочетается одновременно любовь к написанию велосипедов и не умение их писать.
              Ответить
              • лет 5 назад на гейдеве не было ни одного человека, кто пользовался stl в принципе. В ЛЮБОМ случае использовался свой велосипед без оговорочно. С тех пор как я хожу на форум, то стл становится все более популярным. Но вот С++11 игнорируется 90% том гейдевшиков с форума и они объясняют это полной его не состоятельностью. Там народ целые треды заводит, посвящённые тому что он не нужен и с++ должен выглядеть как D или LSD (какой-то парень много раз поднимал тему со своим паскалоподобным языком)
                Ответить
                • ну если для прогромирования игор используется вижуал студия (и, скорее всего, так оно и есть), то отрицание с++11 - вполне объяснимая реакция на пиздец, творящийся у вендоров
                  Ответить
                  • так и есть, студия. но в основном не нравится rvalue, vararg, lambda, auto и тд
                    Ответить
                    • >но в основном не нравится rvalue, vararg, lambda, auto и тд
                      а чем им не угодили rvalue semantics? Это же чистый перфоманс
                      Ответить
                      • Не чистый.
                        Для чистого перфоманса исходный объект надо нафиг забывать. А в кривтах исходный объект надо приводить к состоянию, из которого можно безопасно вызвать dtor.
                        Ответить
                        • А как ты забудешь нафиг исходный объект? Для локальной переменной это может быть еще прокатит, а вот для члена какого-нибудь класса или глобалки - куй. Придется какой-то флаг хранить, что черезголова по памяти.

                          Или есть другие пути?
                          Ответить
                          • Я так понимаю, что move автоматически применяется там, где раньше было copy_ctor; dtor; то есть где объект и так по любому выходил из зоны видимости.
                            Это например возврат значения из функции.
                            Не путать с std::move! std::move разрешается применять к объекту посреди его жизненного цикла, а тот move, про который я думаю - он только для конца жизненного цикла. То есть любой объект в конце жизни должен быть либо уничтожен, либо перемещён.

                            > Придется какой-то флаг хранить, что черезголова по памяти.

                            Да, именно это текущая система и предлагает! Любой объект обязан хранить флаг "не занулён ли", в перемещателе я должен занулять флаг, а в деструкторе проверять флаг на зануление.
                            В моей схеме флаг не нужен. Если объект переместили, то к нему после этого обращаться тупо запрещено, если только не ССЗБ. Это как с ручным вызовом конструктора в нынешней схеме.
                            Ответить
                            • Человек боящийся написать лишний if никогда не сможет написать конкурентоспособную коммерческую программу.
                              Ответить
                              • Человек, который %condition%, никогда не сможет %success_story%.
                                По делу мы с тобой вроде всё на крестофоруме обсудили.
                                Ответить
                                • > %condition%
                                  predicate
                                  Ответить
                                • нахрена тебе флаг вообще? обычно берется указатель зануленный или какое-то специальное значение для члена. так что оверхед по памяти редок
                                  Ответить
                                  • А если я хочу класс "ненулевой умный указатель"? Или "ненулевой умный хенд"?
                                    Ответить
                            • >То есть любой объект в конце жизни должен быть либо уничтожен, либо перемещён.

                              Сначала перемещение его обнулит, а потом он будет уничтожен.


                              >Да, именно это текущая система и предлагает! Любой объект обязан хранить флаг "не занулён ли", в перемещателе я должен занулять флаг, а в деструкторе проверять флаг на зануление.

                              При создании объектов хорошим тоном будет предоставить конструктор без параметров, который не будет захватывать ресурс, и методы для инициализации и освобождения ресурсов. В деструкторе, естественно, происходит освобождение, если есть что освобождать. Таким образом, объект обязан хранить информацию о том, захватил ли он ресурс. Хоть флаг, хоть специальное значение(nullptr, -1, INVALID_HANDLE итп)


                              >Если объект переместили, то к нему после этого обращаться тупо запрещено, если только не ССЗБ.

                              объект остаётся на месте, а его ресурсы переходят к другому объекту и теперь этот другой отвечает за их освобождение
                              Ответить
                              • > Сначала перемещение его обнулит, а потом он будет уничтожен.

                                Так это и есть переголова!
                                Почему нельзя просто нихера с ним не делать?

                                > При создании объектов хорошим тоном будет предоставить конструктор без параметров, который не будет захватывать ресурс

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

                                > объект остаётся на месте, а его ресурсы переходят к другому объекту и теперь этот другой отвечает за их освобождение

                                Я знаю. Если ресурсы объекта перешли другому и сам объект уходит из зоны видимости, то не лучше ли тупо забыть про него?
                                Ответить
                                • >Так это и есть переголова!
                                  БАЙТОЁБСТВО

                                  >Почему нельзя просто нихера с ним не делать?

                                  то есть вместо оперции перемещения и деструктора надо запилить операцию перемещения при выходе из фукнции, перемещения с помощью std::move итд?
                                  Вместо того, что разбить сложные операции на примитивы будем реализововать конкретный каждый случай?

                                  Как в твоей схеме будет работать такая ситуация?
                                  struct A
                                  {
                                      BigStruct b;
                                      AnotherStruct c;
                                      A(A &&other)
                                      {
                                          b = std::move(other.b);
                                      }
                                  };


                                  >А если я хочу блин такой объект, который не может иметь нулевое состояние? То текущая схема не даст мне его создать.

                                  Такое может иметь смысл, если объект живет на стэке и является чем-то вроде mutex_locker

                                  >Да и даже если допустить нулевое состояние - то в текущей схеме имеем переголову на то, чтобы занулять объект, а потом проверять, не занулили ли его.
                                  Maybe boost::option или наиумнейший указатель из соседнего треда


                                  >Я знаю. Если ресурсы объекта перешли другому и сам объект уходит из зоны видимости, то не лучше ли тупо забыть про него?

                                  Про целостность(как языка, так и объекта) тоже лучше забыть?

                                  class A
                                  {
                                      B m_b;
                                      void method()
                                      {
                                           B b = getB();
                                           if (...)
                                               m_b = std::move(b);
                                      }
                                  };
                                  Ответить
                                  • Бля, я сразу сказал, не путай тот move, что предлагаю я, и std::move, у них разная семантика.
                                    Ручной вызов моего move - это операция, которую могут делать лишь те, кто отвечает за последствия, как и ручной вызов конструктора, деструктора итд.
                                    Ответить
                • >>Но вот С++11 игнорируется 90% том гейдевшиков с форума
                  Ничё скоро начнут юзать - за уши не оттянешь. Оно так всегда с достижениями прогресса.

                  PS
                  >>не умение их писать
                  >>не состоятельностью
                  >>без оговорочно
                  Простите, но всё это пишется слитно.
                  Ответить
              • Магистр системной магии рад предложить вам свои услуги!

                Сниму порчу с памяти, верну потерянные указатели, найду забытые деструкторы. Гадание на gdb в присутствии заказчика или по снимку памяти. Дорого.
                Ответить

    Добавить комментарий