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

    +155

    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
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    #include <iostream>
    #include <memory>
    #include <assert.h>
    using namespace std;
     
    template <class T>
    class megaClass
    {
    public:
     
        void hello()
        {
            assert(dynamic_cast<T*>(this)!=NULL);
            static_cast<T*>(this)->hello();
        }
        virtual ~megaClass() {}
    };
     
    class cleft : public megaClass<cleft>
    {
    public:
     
        void hello()
        {
            std::cout << "left::hello()" << std::endl;
        }
    };
     
    class cright : public megaClass<cright>
    {
    public:
     
        void hello()
        {
            std::cout << "right::hello()" << std::endl;
        }
    };
     
     
    int main()
    {
        scoped_ptr<megaClass<cleft> > a1=new cleft;
        a1->hello();
        scoped_ptr<megaClass<cright> > a2=new cright;
        a2->hello();
        
        return 0;
    }

    Пытался продемонстрировать статический полиморфизм TarasB и получилась такая какашка. Кто действительно крут и может сабдж продемонстрировать? Я где-то видел пример, но не помню где...

    Ещё продемонстрировал статический полиморфизм через стратегии:

    struct Strategy1
    {
    static void do(){printf("Lol1");}
    };
    struct Strategy2
    {
    static void do(){printf("Lol2");}
    };
    template<class Strategy>
    class MegaClass
    {public:
    void do()
    {
    printf("Mega");
    Strategy::do();//Класс Strategy можно было и создать для хранения состояния.
    printf("/n\");
    }
    };
    //...

    Дальше в разных частях кода создаем:
    MegaClass<Strategy1> o;
    o.do();
    //...
    MegaClass<Strategy2> o;
    o.do();
    "Один" класс ведёт себя по разному. Понятно, что это не совсем полиморфизм. Но очень часто именно в таком контексте используют динамический полиморфизм, хотя такого статического здесь достаточно выше крыши.
    Плюсы этого подхода :
    1)Создаётся объект в стеке, значит быстро, а не в куче. Хотя можно и не в стеке.
    2)Используется шаблон, значит компиль будет инлайнить.

    Минус:
    1)Если понадобится резкой перейти от статического полиморфизма к динамическому - придётся переписывать на виртуальные функции или на истинный статический полиморфизм.

    Обсуждения здесь:
    http://govnokod.ru/8025#comment110773


    Сразу исключим детсадовский вариант статического функционального полиморфизма c перегрузкой функций:
    Class1 o1;
    foo(o1);
    Class2 o2;
    foo(o2);

    void foo(Class1 o){/*...*/};
    void foo(Class2 o){/*...*/};



    Кто-нибудь реально умеет can into нормальный статический полиморфизм?

    Запостил: CPPGovno, 30 Сентября 2011

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

    • посмотри реализацию std::string
      Ответить
      • Какой компиль? Было бы не плохо, если вы скопипастили немного в тред говница из STL.
        Ответить
        • msvc10 express ed.
          int std::string::compare(const _Elem *_Ptr) const
          {	// compare [0, _Mysize) with [_Ptr, <null>)
          	_DEBUG_POINTER(_Ptr);
          	return (compare(0, this->_Mysize, _Ptr, _Traits::length(_Ptr)));
          }
          ...
          template<class _Elem,
          	class _Int_type>
          	struct _Char_traits
          	{	// properties of a string or stream element
          	typedef _Elem char_type;
          	typedef _Int_type int_type;
          	typedef streampos pos_type;
          	typedef streamoff off_type;
          	typedef _Mbstatet state_type;
          ....
          	static size_t __CLRCALL_OR_CDECL length(_In_z_ const _Elem *_First)
          		{	// find length of null-terminated sequence
          		size_t _Count;
          		for (_Count = 0; !eq(*_First, _Elem()); ++_First)
          			++_Count;
          		return (_Count);
          		}
          };
          ...
          typedef basic_string<char, char_traits<char>, allocator<char> > string;
          Ответить
    • > Сразу исключим детсадовский вариант статического функционального полиморфизма c перегрузкой функций:

      Почему детсадовский? Если несколько копий функции будет писать не программист, а компилятор, то почему бы и нет?
      Ответить
    • Во что скатился уютненький говнокод!
      Ответить
    • CPPGovno, а какой размер поля "Описание говнокода"?
      Ответить
    • //MSVC2010
      #pragma once
      
      #include <iostream>
      #include <string>
      #include <map>
      
      using namespace std;
      
      class Class
      {
      	typedef void (Class::*classMethod)(void);
      	classMethod whatToCall;
      
      	static map<string, classMethod> initMethods()
      	{
      		map<string, classMethod> result;
      		result["zero"] = &Class::method1;
      		result["one"] = &Class::method2;
      		result["two"] = &Class::method3;
      		return result;
      	}
      	const static map<string, classMethod> methods;
      
      	void method1(void) { cout<<"blah-blah-blah"<<endl; }
      	void method2(void) { cout<<"rtfmfm"<<endl; }
      	void method3(void) { cout<<"42"<<endl; }
      
      	static classMethod methodByStr(const string& name)
      	{
      		auto it(methods.find(name));
      		if(it==methods.end())
      			return nullptr;
      		else
      			return it->second;
      	}
      
      public:
      	Class() : whatToCall(nullptr) { }
      	Class(const string& name) : whatToCall(methodByStr(name)) { }
      	void imNotUsingVirtualFunctions() { (this->*whatToCall)(); }
      };
      
      const map<string, Class::classMethod> Class::methods = Class::initMethods();
      Ответить
      • где тут статический полиморфизм?
        у тебя ран-тайм полиморфизм
        Ответить
        • >>1)Создаётся объект в стеке, значит быстро, а не в куче. Хотя можно и не в стеке.
          done
          >>2)Используется шаблон, значит компиль будет инлайнить.
          А в результате - приведение типов через reinterpret_cast, нельзя создать массив полиморфных объектов без е..ли и вообще грязь в коде. Смысл?
          Ответить
          • смысл в инлайне
            вызовы функций через указатели не инлайнятся. более того, если на функцию создатся хотя бы один указатель, она вообще не может инлайнится
            Ответить
    • -у с++ особый нрав. это как необузданный мустанг из прерий
      -точно, а я то думаю, кого он мне напоминает
      -но зато он самый быстрый, сильный и гибкий
      но чуть ты оплашаешь - обязательно упадешь на большой скорости вниз под копыта
      приготовься и запасись терпением. пройдет много времени, прежде чем он тебя зауважает и ты почувствуешь себя его хозяином
      Ответить
    • Нашёл:
      template <class Derived> 
      struct Base
      {
          void interface()
          {
              // ...
              static_cast<Derived*>(this)->implementation();
              // ...
          }
       
          static void static_func()
          {
              // ...
              Derived::static_sub_func();
              // ...
          }
      };
       
      struct Derived : Base<Derived>
      {
          void implementation();
          static void static_sub_func();
      };

      См Static polymorphism в
      http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern
      Ответить
    • Кстати, Тарасу на заметку: Использование Pimpl экономит 1 вызов по указателю. Ибо виртуальные функции это вызов через 2 указателя.
      Ответить
      • и так, поясню мысль для проминусовашегося:

        для виртуальных функций:
        первый указатель: указатель на объект (он есть, даже если объект создан в стеке)
        второй указатель на VTBL (таблицу виртуальных методов)
        третий указатель на виртуальный метод

        для не виртуальных методов:
        тупо вызывается метод, с зафиксированным константным адресом в опкоде комманды call, что намного быстрее для вызова, даже чем через обычный 1 указатель.
        Ответить
        • class a {
          virtual void do_();
          };
          
          class b {
          virtual void do_();
          };
          
          a *p = new b;
          p->do_(); // this->vtable[DO_](); ессно выбирается <vtable> для [b]
          Ответить
          • Как это удалось скастовать указатель на b в указатель на a?
            Ответить
            • Наверное забыл наследовать от "class a".
              Меня ещё смущает как удалось вызвать приватный метод.
              Ответить
          • да бля косяк вышел с наследованием

            впрочему похуй. кто в теме и так знает, а кто не в теме, тот не поймет нихуя
            Ответить
            • Дак вы в теме или нет?
              По-моему мнению, объяснить вы не смогли, ни простыми, ни сложными словами.
              Ответить
        • Если объект локальный, то умный компилятор в таблицу виртуальных функций лезть не будет.

          И да, Pimpl — это немного не то.
          Ответить
      • Использование ТВМ прописано в стандарте?
        Ответить
        • На практике все делают именно так, да и не сделаешь по другому особо.
          Ответить
          • Можно и по-другому.
            Ответить
            • Примеры?
              Ответить
              • Например, хранить в объекте указатели на методы. Так делают ООП на Си и в языках, где можно изменить метод для отдельного объекта. Больше расход памяти (пропорциональный количеству объектов и количеству методов), но на один уровень косвенности меньше при вызове. Если в некоторой иерархии всего один виртуальный метод и не используется rtti, то оверхеда нет и это бесспорная оптимизация.

                Можно придумать и другие способы. Например, в виртуальной таблице хранить не указатели, а сами методы (в элементах фиксированного размера). Небольшие поместятся все, для больших — команда перехода (или начало и команда перехода). Увеличение расхода памяти не зависит от числа объектов, и на один уровень косвенности для малых методов меньше (для которых это имеет смысл).

                Можно избавиться от указателя на таблицу, если объекты разного типа распределять в разных областях памяти. Тогда тип однозначно определяется указателем (старшими битами). В принципе, это реально организовать даже на современных 64-битных процессорах. С стековыми объектами придётся повозиться (по сути на стеке это будут только прозрачные умные указатели), этот способ больше подходит для Java или C#.
                Ответить
                • >Например, хранить в объекте указатели на методы. Так делают ООП на Си
                  Это понятно. Только вот на си этот метод не к месту. Если пишешь для небольших контроллеров - каждый байт на счету. А тут растраты на пустом месте...
                  Ответить
                  • Для контроллеров можно и без ООП обойтись. А вот если гуйня…
                    Ответить
                    • Между прочем сишники упорно, даже для контроллеров, продолжают эмулировать ООП. То, что оно удобно заставляет их использовать это периодически и ничего в этом плохого нет. Есть разные задачи для контроллеров, где это уместно. Для контроллеров даже на С++ пишут.
                      Ответить
                • Любой из таких способов оптимизации неоправданно усложняет компиль.
                  Ответить
                  • А компилятор C++ и так очень непростой. Это не усложнит его и на 1%. Правда, и выгода будет в очень специфических случаях. Хотя…
                    Ответить
                    • >выгода будет в очень специфических случаях
                      Не имеет смысла усложнять на один процент из-за почти отсутствующей выгоды.
                      Ответить
                      • Это в среднем по больнице. Для одних приложений выгоды не будет, для других — будет.
                        Ответить
                        • 1% в редких программах на редком вызове? Это даже не стоит обсуждать. Экономия на спичках.


                          >Если в некоторой иерархии всего один виртуальный метод и не используется rtti, то оверхеда нет и это бесспорная оптимизация.

                          Ох какая бесспорная... Виртуальных методов обычно или 0 или >=2. Случая с одним просто нет. Обычно, если появляется хоть один метод, то сразу появляется и виртуальный деструктор. А rtti вообще по стандарту языка должен быть, если есть виртуальные методы. А rtti это ещё один указатель\виртуальный метод.
                          Ответить
                          • Нет, в редких программах, вовсю использующих быстрые виртуальные объекты-функторы, выгода может быть намного больше, десятки процентов. Да, при этом эти объекты не должны передаваться во владение. Создали объект, передали по ссылке/указателю в функцию, где он используется миллион раз, после возврата сами же и уничтожили.

                            RTTI должен быть, если его используют. А если нет для какой-то иерархии dynamic_cast или typeid, то и не нужен.

                            Эту оптимизацию и вручную сделать можно, указателем на функцию, но если компилятор сам заметит, приятно.
                            Ответить
                            • >RTTI должен быть, если его используют.
                              Если хоть в одном классе данной иерархии он используется, то его придется использовать везде, иначе кастить не получится этот объект.

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

                              А с учетом современных тенденций: один класс предок на всю иерархию программы, например как QObject в QT или System.Object в C#, то эта оптимизация совсем работать не будет.

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

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

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

                              Если вам что-то не нравится, то напишите свой компилятор или вы знаете, где найти assembler и ansi C для экономии на редко встречающихся спичках в своих программах.
                              Ответить
                              • Вы часто используете dynamic_cast и typeid? Я — нет, а когда использую, это ограничивается небольшой определённой иерархией классов. C++ позволяет не производить классы от одного суперкласса, и большинство пользовательских классов таки не наследуются от него, даже если используются библиотеки с суперклассами (у каждой своим).

                                Некоторые способы оптимизации (например, dynamic_cast за O(1)) требуют знание о всей иерархии классов. Сейчас компилятор и редактор связей намного умнее, чем были 30 лет назад.
                                Ответить
                                • >Вы часто используете dynamic_cast и typeid?
                                  Я - нет, но QT все время. Выигрыш от метода теряется полностью на всех классах QT приложения.

                                  >Сейчас компилятор и редактор связей намного умнее
                                  Вот только не надо. Вижу я этот "ум и гениальность" межмодульной оптимизации каждый день, особенно в GCC или MSVC... И это при часовых компиляциях. А что будет, если добавить ещё больше "ума" межмодульному оптимизатору?

                                  Не подходит С++ для нормальной межмодульной оптимизации., особенно с его препроцессором и включаемыми файлами. 2 этих фактора нарушают легкость межмодульной оптимизации. Компилятору приходится генерировать код, не нарушающий ODR (я про ODR машинного уровня, а не уровня кода), что не так просто, если сделать его "сильно умным" и при этом ошибиться хоть где-нибудь.
                                  Ответить
                                  • С QT не сталкивался, но используя Qt, не обязательно все свои классы наследовать от QObject (и в Qt не все классы входят в эту иерархию). Да вы можете использовать классы вообще без виртуальных методов и какой-либо vtable.
                                    Ответить
                                    • >С QT не сталкивался

                                      Ну и говорить нечего тогда. За чем тогда в спор ввязались? С этим не сталкивались... Этого не знаете... Этого не умеете... и тд...


                                      >Да вы можете использовать классы вообще без виртуальных методов

                                      Спасибо, за разрешение.
                                      Ответить
                • Если убрать указатель на VTBL, используя эти нестандартные оптиизации, то пропадет совместимость экспортируемых объектов COM, а сейчас оный и его аналоги даже в линуксе используются.
                  Ответить
                  • Какой ещё ком-шном? Ничего такого в стандарте языка нет. А C++ всегда был ориентирован на монолитные блобы, и многие оптимизации рассчитаны на доступность всего кода. Для внешних интерфейсов можно использовать общепринятый ABI, а что там внутри — это наше дело.
                    Ответить
                    • >Ничего такого в стандарте языка нет.
                      Зато есть стандарт де факто и его также желательно поддерживать. Иначе под туже винду нельзя будет легко писать, ибо там COM в моде, особенно с выходом "ЭпикВин8".
                      Ответить
                      • Эка невидаль. Под винду и так нельзя писать на современных C и C++.
                        Ответить
                        • Вы это скажите тем, кто по прежнему пишут. Да и не нужно забывать о C++\CLI, на коем пишут и под .NET Framework под винду и могут юзать COM. А под винду 8ку появится и C++\CX, на который делает ставку майкрософт в ущерб даже шарпам и прочим управляемым языкам.

                          Вообщем, терять совместимость из-за копеечных сомнительных оптимизаций при усложнении компиля - не вариант.
                          Ответить
                          • Ну вот, под винду свой особый диалект C++, несовместимый со стандартом. Всё равно ведь для того, чтобы сделать COM, нужны дополнительные действия, за пределами языка? И ничто не мешает это использовать для внутренних классов, невидимых снаружи. На совместимость это не повлияет. Может быть нужны будут специальные подсказки компилятору (прагмы), а может и сам догадается.
                            Ответить
                            • >Ну вот, под винду свой особый диалект C++, несовместимый со стандартом.

                              Может для вас это секрет, но все компиляторы до конца не совместимы со стандартом.


                              >Всё равно ведь для того, чтобы сделать COM, нужны дополнительные действия

                              На GCC или ANSI C в легкую делается COM не выходя за пределы языка.


                              >Может быть нужны будут специальные подсказки компилятору (прагмы),

                              Костылей и так хватает. Нечего добавлять новые.
                              Ответить
                              • И как C обходится без vtable?
                                Ответить
                                • Завести в структуре указатель на структуру указателей на методы не дано?
                                  Ответить
                                  • А порядок методов? А место для RTTI? Всё это хаки, частности реализации, нестандартные и непереносимые.
                                    Ответить
                                    • >А порядок методов?

                                      Все уже продумано и во всю используется. Почитайте хотя бы про COM, ABI, что б хоть представлять что это такое. Я уже говорил про стандарт де факто, который вы так хотите нарушить.
                                      Ответить
                                    • >А место для RTTI?
                                      Кстати, оно в отрицательном смещении таблицы VTBL.
                                      CPPGovno
                                      Ответить
                                      • уходя уходи
                                        Ответить
                                        • Меня, кстати, не забанили. Могу зайти под своим ником, но не буду больше никогда.
                                          .
                                                                         C++Govno
                                          Ответить
                                          • http://s4j.clipsonline.org.ua/127371690151580.jpg
                                            Ответить
                                            • Вы же понимаете, что раз я решил уйти, то не буду логиниться или заводить новый акк?
                                              .
                                                                      C++Govno
                                              Ответить
                • >Например, хранить в объекте указатели на методы, а не указатель на таблицу виртуальных методов.

                  Не кэшфрендли.
                  Ответить
                  • Я не говорю, что это хорошо, но это реальный способ, он использовался ещё тогда, когда ни о каких внутрипроцессорных кешах никто и не слышал. И продолжает использоваться и поддерживаться сейчас.

                    Ещё один недостаток — увеличивается время создания объекта (нужно проинициализировать все указатели на методы).
                    Ответить
                    • >Я не говорю, что это хорошо
                      Тогда и предлагать нечего.

                      >И продолжает использоваться и поддерживаться сейчас.
                      примеры?

                      Я и так знаю, что он использовался при царе горохе. Но это не серьёзно. Не зря же пришли к VTBL.
                      Ответить
                      • Это не я предлагаю, это так есть. Полагаю, что GTK и сейчас так устроено. Qt, кстати, со своими динамическими сигналами, тоже. Вообще, любая гуишная ОО модель содержит в объектах сказатели (или списки указателей) на обработчики. Практически каждый динамический ОО язык.
                        Ответить
                        • >любая гуишная ОО модель содержит в объектах сказатели (или списки указателей) на обработчики
                          Что за капитанство? Qtшные классы во внутреннем устройстве не имеют никакого то отклонения от стандарта де факто, использующего VTBL. Все компилится и обычным С++ компилем + кодогенератором препроцессорного типа. Ничего менять в устройстве класса из-за QT не нужно и никто этого не делает.

                          >это так есть.
                          Я ещё раз спрашиваю примеры?

                          >Полагаю
                          Нечего полагать. Я жду фактов или объяснения большей оптимальности или необходимости такого метода.
                          Ответить
                          • С GTK я работал достаточно давно, не помню, как там устанавливаются обработчики. Но любая современная объектная гуишная система имеет либо члены в объектах, куда сохраняются указатели, либо глобальный реестр (как в FOX Toolkit) — тоже способ реализации виртуальных методов, громоздкий и медленный.

                            Компилируется Qt не обычным компилятором C++, используются свои расширения языка, которые уже компилируются в C++. Напомню, что первый компилятор C++ компилировал в C.
                            Ответить
                            • >Но любая современная объектная гуишная система имеет либо члены в объектах, куда сохраняются указатели — тоже способ реализации виртуальных методов, громоздкий и медленный.

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


                              >Компилируется Qt не обычным компилятором C++

                              Я уже сказал, что QT проги компилируется обычным компилятором С++, предварительно прогнав код через кодогенератор препроцессорного типа. Теперь понятно, почему аргументы не доходят до вас и вы продолжаете без конца повторять одно и тоже. Если вы не внимательно читаете, то я не могу ничем вам помочь. Я не могу читать за вас. Видимо, это сигнал мне закончить разговор с вами.
                              Ответить
                • >Например, в виртуальной таблице хранить не указатели, а сами методы (в элементах фиксированного размера).

                  Это вообще не слабое разбухание кода для очень разветвленных иерархий. Придется на каждый отдельный класс хранить свою таблицу кода абсолютно одинаковых функций.
                  Ответить
                  • Не такое уж сильное, ведь в таблицу поместятся только небольшие функции. Будет не 8 байт на метод, а пусть 128, таблица класса с полусотней методов займёт не 400 байт, а на 6 килобайт больше — тьфу. Большие функции всё равно займут килобайты и десятки килобайт. Так что в процентном отношении код вырастет не сильно. А если ещё учесть мегабайты данных…
                    Ответить
                    • >таблица класса
                      А таких классов может быть много, не забывайте обо всех потомках и предках этого класса в иерархии с перекрывающими методами. А это много классов с абсолютно одинаковыми копиями методов. Особенно эпичный фейл ждет, если вспомнить современные тенденции к кодогенерации и шаблонам, то это уже будет нереально много классов с абсолютно одинаковыми копиями методов.

                      И вообще это не кешфрендли.

                      Хватит предлагать методы, что не подходят современным реалиям, а использовались разве что отцами.
                      Ответить
                      • А может быть и не много (по сравнению с количеством объектов). Например, в геометрической модели ограниченное число классов (вершины разного типа, рёбра, грани и полигоны разного типа), размер каждого объекта — от 32 до сотни байт, а самих объектов — миллионы (т.е. данные занимают места на несколько порядков больше кода). Виртуальные методы могут быть достаточно просты (количество вершин элемента, вершина по номеру), чтобы лишний уровень косвенности при вызове был но заметен. Если компилятор, пошуршав несколько часов, выдаст бинарник, который просчитывает задачу на 20% быстрее, — честь ему и хвала.

                        Кстати, о кеше. Если разделять кеш для данных и кода, то код пары десятков классов осядет в кеше, а вот vtable с указателями будет постоянно выталкиваться из него обрабатываемыми данными. Но это частности.
                        Ответить
                        • >А может быть и не много

                          А может быть, да кабы, да во рту выросли грибы. Из-за кодогенерации и шаблононов С++ классов очень много. Не хочу иметь дубликат всех функций map для каждой комбинации его шаблонных параметров. Проект и так долго компилируется, а тут ещё и кучу дубликатов. Полумеры не рулят. Ещё этот метод заставляет вставлять лишние джампы в конце каждой большой функции из таблицы, что также не кешфрендли.


                          >а вот vtable с указателями будет постоянно выталкиваться из него обрабатываемыми данными

                          Да ладно? Обычно виртуальные функции используются часто, так что не будет выталкиваться.


                          >от 32 до сотни байт, а самих объектов — миллионы

                          Эта задача - ещё один сферический кот в вакууме, которых вы так любите приводить в качестве примеров.


                          >Если компилятор, пошуршав несколько часов, выдаст бинарник, который просчитывает задачу на 20% быстрее, — честь ему и хвала.

                          Чтобы получить приличный прирост к производительности - нужно оптимизировать алгоритм, а не экономить на спичках (на инструкциях). Компилятор за вас говноалгоритм не перепишет. Если же вам нужна экономия на спичках, я уже сказал, где её найти (Си\асм).
                          Ответить
                          • std::map не имеет виртуальных методов.

                            Джамп (только не в конце, а в начале-середине) больших функций как раз соответствует текущей модели vtable.

                            Ну что поделать, вот с такими сферическими конями приходится иметь дело. Это комы да дотнеты для меня экзотика.

                            Писать такое на Си или, тем более, ассемблере — безумие, код засорится и помешает высокоуровневой оптимизации. А вот если компилятор бесплатно и прозрачно её проведёт, то можно на такие детали не обращать внимания и заняться алгоритмами.
                            Ответить
                            • >Джамп в начале больших функций как раз соответствует текущей модели vtable.

                              Поэтому и не было смысла вводить эту оптимизацию. Если вспомнить все вышеперечисленные её недостатки.


                              >std::map не имеет виртуальных методов.

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


                              >можно на такие детали не обращать внимания и заняться алгоритмами.

                              Вот и займитесь этим наконец. Не нужно валить все беды с больной головы на здоровую. Нечего обвинять компилятор во всех грехах. Если что-то тормозит - программист написал плохой код и использовал плохой алгоритм. Из-за вашей экономии на спичках прироста не будет, а как мы выяснили уже - одни беды.
                              Ответить
                • >Можно избавиться от указателя на таблицу, если объекты разного типа распределять в разных областях памяти. Тогда тип однозначно определяется указателем (старшими битами).

                  Хаки какие то. Это особенно поможет, когда предков у класса 100500. Заведем бесконечное адресное пространство и будем перед каждым вызовом виртуальных функций делать побитовые операции (мега оптимизация) и не понятно как потом определять, какой виртуальный метод вызвать. При этом со стеком в С++ этот метод ждет фейл и тормоза, тк нужно дергать медленный менеджер памяти, а не быстрый стек. И да, придется сделать "особый магический" менеджер памяти для размещения в разных адресах адресного пространства, предварительно переписав ОС, чтобы та позволяла 100% разместить все объекты по конкретным адресам и быстро. А когда адресное пространство с данным битом заполнится до отказу объектами данного типа, программу ждет bad_alloc при почти пустой памяти, а программиста батхерт. Нечего было создавать так много объектов данного типа! Особенно забатхертятся программисты под DOS. Эпичный пафос и пафосный эпос. (:
                  Ответить
                  • *"Это особенно поможет, когда потомков у класса 100500."
                    fix
                    Ответить
                  • Выделим старшие 20 бит на код класса — миллиона классов хватит? Битовые операции могут быть быстрее обращения к памяти (особенно, если будет поддержка процессором). Виртуальный метод определяем точно так же, по индексу в таблице, адрес которой дадут старшие биты адреса объекта. Менеджер памяти будет почти такой же быстрый, как стек, ведь он работает с объектами одинакового размера. ОС переписывать не нужно, если только она не написана на C++, всё необходимое уже поддерживается. Доступное для класса адресное пространство на порядки превышает доступные в обозримом будущем объёмы физической памяти (и только на инициализацию понадобиться много времени).

                    DOS? 64-битный DOS?
                    Ответить
                    • >DOS?
                      А по вашему GCC не должен компилировать под DOS или под микроконтроллеры? А то что этот метод не совместим с текущими отлаженными бекендами вас не смущает? А то что этот метод не совместим с текущим стандартом С++, например с кастомными аллокаторами или перегрузкой операторов С++ вас тоже не смущает? А то что это метод сильно замедляет работу со стековыми объектами, взамен мелкой экономии на спичках - вас это также не смущает? А то, что винда не позволяет выделять с гарантией по конкретным адресам объекты и может выделить при этом без смущения по другим? С системой куч винды это не совместимо. И тем более винда не позволяет выделять память по заданным регионам? Вас не смущает, что оси придется переписывать. А не смущает ли вас, что в разных версиях осей какие то диапазоны заняты под системные объекты полностью и не доступны для выделения, зато они доступны в других? Придется под каждую ось компилировать отдельно?

                      Хватит предлагать котов в вакууме.
                      Ответить
                      • Где вы взяли 64-битный DOS и зачем? И почему вы против архитектурно-специфичных оптимизаций?

                        К перегрузке операторов это не имеет никакого отношения. Работу с автоматическими переменными практически не замедлит (в той же области видимости всё равно виртуальность исчезнет). Как там в виде не знаю, это её проблема, ну значит будут под неё программы медленнее. А так ведь можно отмапить максимально возможное адресное пространство и использовать по своему усмотрению. Не думал, что в современных ОС прикладные программы работают с физической памятью и по абсолютным адресам. Ну да это проблемы этих ОС (кстати, обычно программы таки компилируются отдельно под разные ОС и под разное железо, иногда даже разными компиляторами).
                        Ответить
                        • >Где вы взяли 64-битный DOS и зачем?

                          Мне интересно, где вы его взяли? А С++ компилятор должен компилировать и под DOS и под МК, но я вам уже это говорил. Но видимо, для вас нужно много раз повторить, прежде чем дойдет.


                          >И почему вы против архитектурно-специфичных оптимизаций?

                          Вот когда поработаете над кроссплатформенными проектами, тогда и поговорим. См ниже.


                          >К перегрузке операторов это не имеет никакого отношения.

                          Да ладно? А как же вы через стандартный malloc затребуете память по определенному региону? Если это архитектуро-специфичная "оптимизация", то как же вы будете перегружать оператор new? Под одну платформу с использованием регионов, а под другую без? Решили добавить ещё одну причину писать программисту дубликаты кода под разные платформы? Обойдемся.


                          >Работу с автоматическими переменными практически не замедлит.

                          Замедлит и ещё как. В стеке память выделяется за одну инструкцию проца, а вы предлагаете вызывать тормозную кучу с очень большим не детерминированным временем выделения и освобождения памяти. А между тем автоматических объектов в С++ большинство в среднестатистической программе. "Хорошая" оптимизация у вас получилась...

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


                          >Ну да это проблемы этих ОС
                          По моему эта ваша личная проблема и пользователей вашего "компилятора".


                          >Не думал
                          Знаю.
                          Ответить
                          • Это вы зачем-то приплели DOS. В разговор о деталях реализации для 64-битных машин с виртуальной страничной памятью.

                            Это (а также другие ваши реплики) показывает, что вы совершенно не слушаете собеседника, а значит продолжать эту дискуссию бессмысленно. А с учётом вашего тона — и нежелательно.
                            Ответить
                            • >вы зачем-то приплели DOS. В разговор о деталях реализации для 64-битных машин с виртуальной страничной памятью.

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


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

                              Аналогично, я про вас это уже сказал и повторятся не буду.
                              Ответить
                            • Хех. Неужели довел вас до батхерта?
                              Надо быть сдержаннее. (:
                              Ответить
                          • Верните школьников более ранних классов, что вы тут бадягу разводите, готовьтесь лучше к ЕГЭ, не занимайте аккаунт.
                            Ответить
    • static void do(){printf("Lol1");}

      Я один заметил, что зарезервированное слово используется в качестве идентификатора?
      Ответить
    • :-) void * - и только на с. Рекомендую тсс, зверек неухоженный но классы дергает только так даже в режиме интерпретатора. и собирай на месте хоть франкенштейна из 10 разных классов :-)
      Ответить
    • показать все, что скрытоvanished
      Ответить

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