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

    −29

    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
    calculateSomething(int n){
    	float* x = new float[n];
    	/*do smth*/
    	
           if ( /*validation*/ ) {
    		delete[] x;
    		return;
    	}
    	
    	float* y = new float[n];
    	/*do smth*/
    	
    	if ( /*validation*/ ) {
    		delete[] x;
    		delete[] y;
    		return;
    	}
    	
    	float* z = new float[n];
    	/*next step*/
    	
    	if ( /*smth goes wrong*/ ) {
    		delete[] x;
    		delete[] y;
    		delete[] z;
    		return;
    	}
    
            /*more calculations with validation*/
    
           delete[] x;
           delete[] y;
           ...
           /*more delete[]*/
           
           return;
    }

    Принципиальная схема говногода, найденного на просторах сети.

    Запостил: interested, 26 Июня 2012

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

    • Ну для С нормальный код. А для с++ надо бы воспользоваться RAII.
      Ответить
      • void calculate_something(size_t n)
        {
             float *x, *y;
             x = malloc(n*sizeof(float));
             /*do smth*/
             if ( /*validation*/ )
                     goto EXIT_X;
              /*...*/
              y = malloc(n*sizeof(float));
              /*do smth*/
              if ( /*validation*/ )
                      goto EXIT_Y;
              /*...*/
              EXIT_Y:  
                            free(y);
              EXIT_X:  
                            free(x);
        }
        Ответить
        • Вообще, тоже достаточно опасно.
          Здесь нужно соблюдать порядок между этими EXIT_ и порядком создания, ошибкоопасно.
          Если есть возможность безопасно вызвать free на нулевой, скажем, указатель, то лучше все инициализировать вначале нулями, а в самом конце все освободить, и туда, в конец, бросать из всех неудачных валидаторов. Хотя код всё же придётся менять в двух местах, но уже не по всей функции.
          Ответить
          • > Если есть возможность безопасно вызвать free на нулевой, скажем, указатель
            Конечно есть.

            Вы правы - лучше сделать одну метку, после которой стоит пачка free.
            Ответить
            • А стало быть, и x, и y, и z объявить сразу же в начале функции.
              Ответить
              • Конечно, иначе придется писать нечто в духе:
                double *x = malloc(n*sizeof(float));
                if (/*some*/) {
                   double *y = malloc(n*sizeof(float));
                   ...
                   free(y);
                }
                free(x);
                Ответить
          • >Вообще, тоже достаточно опасно.
            Программирование на С вообще достаточно опасное занятие.
            Но мы ведь не боимся трудностей, правда?

            >Если есть возможность безопасно вызвать free на нулевой, скажем, указатель
            то лучше все инициализировать вначале нулями
            $ man 3 malloc

            The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

            The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable. On error, these functions return NULL. NULL may also be returned by a successful call to malloc() with a size of zero, or by a successful call to calloc() with nmemb or size equal to zero.

            Если вы обратили внимание переход по меткам осуществляется в порядке обратном выделению памяти. т. е. если происходит переход на EXIT_Y, то это значит, что код
            по Х -ветке отработал успешно(понятно что в в этом упрощённом примере, не принимается во внимание действия м/у выделением памяти и некой валидацией, хотя что там ещё может быть, как не проверка валидности выделенной памяти — не знаю).
            Ответить
            • Просто эти EXIT_, как мне кажется, которые обязаны быть расположенными в верном порядке относительно аллокации, будут источником дополнительных проблем при изменениях кода, если вдруг будет нужно. Хотя вероятность этого мала. Но это в данном случае.
              А мало ли что ещё может взбрести в голову программистам, которые и в простом случае, да ещё и на C++ умудряются такое выдать.
              Ответить
            • И все таки способ с одной меткой для данного случая лучше:
              {
                  double *x, *y, *z;
                  x = malloc(n*sizeof(float));
                  if (/*something bad*/)
                      goto cleanup;
                  y = malloc(n*sizeof(float));
                  if (/*something bad*/)
                      goto cleanup;
                  z = malloc(n*sizeof(float));
                  if (/*something bad*/)
                      goto cleanup;
                  /* do something */
              cleanup:
                  free(x);
                  free(y);
                  free(z);
              }
              Ответить
              • Он лучше, пока не забываешь инициализировать автоматические переменные простых типов в стеке:
                {
                    double *x=NULL, *y=NULL, *z=NULL;
                    x = malloc(n*sizeof(float));
                    if (/*something bad*/)
                        goto cleanup;
                    y = malloc(n*sizeof(float));
                    if (/*something bad*/)
                        goto cleanup;
                    z = malloc(n*sizeof(float));
                    if (/*something bad*/)
                        goto cleanup;
                    /* do something */
                cleanup:
                    free(x);
                    free(y);
                    free(z);
                }
                Вот в таком виде это действительно будет работать. При этом не обязательно использовать malloc free, а можно и new[]/delete[].
                Ответить
                • Чувак! Да, ты такой простой тип, что я тебя сейчас инициализирую. ;) (j/k)
                  Ответить
                • Тьфу, ну как я забыл то эти NULL'ы. Сам же писал ниже "конечно же не забыв в начале функции проинициализировать указатели NULL'ом".

                  > При этом не обязательно использовать malloc free
                  Я предполагал, что это С. А на с++ ни к чему эти извраты.
                  Ответить
                • Вот как раз суть: в примере, со множественными метками, инициализация переменных не нужна. Ибо освобождаться будут только те что, не прошли валидацию.
                  Их NULL'ами инициализирует malloc() , в случаи фейла.
                  Ответить
                  • >Их NULL'ами инициализирует malloc() , в случаи фейла.
                    Не инициализирует, если выполнение туда не дойдет.
                    Ответить
                    • Но тогда он и не вызовет free() на них. Все ок.
                      Ответить
                      • Вызовет для случая с одной меткой:
                        cleanup:
                            free(x);
                            free(y);
                            free(z);
                        Ответить
                        • Саид здесь рассматривает случай с множественными метками.
                          Ответить
                    • Да, не точно сформулировал мысль — обед, такой обед.

                      В случае с одной меткой, освобождение будут проходить все ресурсы
                      вне зависимости от того были ли они использованы при попытке выделения памяти или нет.
                      В случае с множественными метками, освобождение будут проходить только те
                      ресурсы, которые на момент не прохождения валидации одним из ресурсов
                      были инициализированы, а также сам ресурс(на ктором malloc() обфейлился, но инициализировал его NULL'ом).
                      Ответить
        • в C еще был способ - заводится переменная типа int runlevel = 0; после очередного захвата ресурса её значение увеличивается на 1
          для наглядности можно параллельно иметь enum с говорящими именами
          в случае ошибки из всех мест делается единый goto cleanup
          а там уже делается switch (runlevel) с кейсами последовательно от максимального значения до 1 без брейков
          Ответить
          • Ну в данном случае можно просто прыгнуть на cleanup, после которого стоит пачка free (конечно же не забыв в начале функции проинициализировать указатели NULL'ом).

            А ваш способ с runlevel он, скорее, для ресурсов типа файлов и сокетов.

            Еще вариант для С, которым я пользовался - заполняем переменные NULLами (или -1 если у нас файлы или сокеты), при ошибке прыгаем на cleanup, где для всех не NULL'овых (не -1) переменных вызываем соответствующую функцию освобождения ресурса.
            Плюс - хорошая развязка между кодом, который получает ресурсы, и кодом, который их освобождает (не надо поддерживать runlevel или писать дополнительные метки, не имеет значения порядок получения ресурсов).
            Минус - немного медленнее, порядок освобождения может не совпасть с порядком получения.
            Ответить
          • Я заметил одну странную вещь. При любом мирном разговоре именно ваши посты получают по +1, хотя оппонент тоже втирает не менее умные вещи. Как будто это какая-то форма нарциссизма через виртуалов.
            Ответить
            • > 3 за и 2 против
              странно, Тарас, не правда ли?
              Ответить
              • Это компенсаторы. Один из них - я.
                Ответить
                • ты так сказал, как будто похвалился
                  повзрослей уже
                  Ответить
                  • Судя по твоей реакции, я угадал в своих подозрениях.
                    Ответить
                    • не надо мерять всех людей по себе, Тарас
                      за логами сколько у меня аккаунтов на гк - к страйкеру
                      боюсь, ответ тебя удивит
                      Ответить
                    • Теория заговора...
                      Ответить
                      • Заговор на успех, читать на перекрёстке трёх кладбищ в полночь.
                        Ответить
                    • Тарас, я частенько плюсую комменты @defecate-plusplus. Не потому, что имя юзера указано в заголовке, а потому, что содержимое открывает для меня что-то новое. Действительно, завязывай уже с кармадрочеством.
                      Ответить
                      • молчи, виртуал, не пали контору!
                        Ответить
                      • Странно, коменты у него точно такие же, как у собеседника, а плюсы только у него.
                        Ответить
                        • Так беспокоиться о плюсах, может только тот кто конвертит их в wmz, например.
                          Ответить
                          • Плюсую. Минусую. Недорого. Писать в личку.
                            Ответить
                • Я всегда думал, что возможность голоса за комментарии существует, что бы выражать своё мнение о содержании комментария в более быстрой, короткой и однозначной форме, чем ответное комментирование. Оказывается тут целые тайные общества (масонские ложи?), холивары виртуалов...
                  Ребята, зачем усложнять себе жизнь?
                  Тарас, ходят слухи, что у тебя баттхёрты по поводу минурастов. Искренне, скорейшего выздоровления тебе.
                  Ответить
                  • Моё нижайшее сожаление, хотел плюсануть и промахнулся. Впрочем, нам, некармадрочерам, это не так важно.
                    P.S. В говнокоде++ хочу возможность переголосовать в течение некоторого времени. И разнести чёртовы кнопочки.
                    Ответить
                    • Да, расположить их так, что бы кнопки находились по разные стороны от рейтинга...
                      Ответить
                      • Обязательно. Кстати Лур не забросил проект?
                        Ответить
                        • Пока никаких новостей не поступало. Траблы с дизайном, как мне кажется.
                          Ответить
                          • Хрен с ним, с дизайном. По мне так хоть голый текст с табличной версткой, лишь бы функционал был ;)
                            Ответить
                            • >голый текст с табличной вёрсткой
                              Это воистину худший вариант. Даже просто голый текст - и то лучше...
                              Ответить
                            • И API, которое дёргать своим ридером.
                              Ответить
                              • Точно! Пускай лур запилит только API и выложит его спецификации. А каждый уже напишет себе клиента по душе. Вот и небольшая защита от дыхоты и нубов - пока кто-то не выложит для них клиента ;)
                                Ответить
                                • Со встроенным вишмастером.
                                  Ещё можно хвалиться, у кого код наиболее говняный. Особые мастера могут написать ридер на баше.
                                  Ответить
                          • Вряд ли с дизайном должны быть проблемы. Сами варианты, которые выдвигал Люр к обсуждению жизнеспособны и более чем удовлетворительны для юзера. И модуль подключения тем к движку сайта он написал. Так что сделать дизайн, хотя бы и слизанный с уютненького, - не проблема. К тому же Кузя обещала оказать помощь именно в этой области.
                            Ответить
                            • Нет педиастра - нет гк2 ;)
                              Ответить
                              • Срочно пять кубиков внутривенно всех раков в тред!
                                [offtop]Bormand, начинает казаться, что вы смайлофажите.[/offtop]
                                Ответить
                                • > всех раков в тред!
                                  Ага, на закуску к пиву.

                                  [offtop]Кто смайлофаг ;) Я ;) Как вы это определили? )))[/offtop]
                                  Ответить
                          • траблы, но не с проектом, а с реалом. наступил период, в который тупо не хватает времени и сил спокойно покодить вечерком
                            Ответить
          • Метки заменены на case'ы, а индексы на метках (_X, _Y) на счётчик runlevel'ов.
            По сути - тоже самое, но в профиль.
            Про ресурсоёмкость не пишу, ибо компиляторы нынче шибко умные пошли.
            Ответить
            • именно, что по сути - да, а по технике исполнения разные - можно совсем отказаться от goto, реализовав всё, что нужно на одной переменной runlevel, цикле do { } while(0);, брейках из него на каждую ошибку и вышеуказанный свич в конце
              goto хейтеры довольны
              Ответить
              • А двойной брейк?
                Ответить
                • нижний
                  wtf двойной брейк?
                  Ответить
                  • Выход из вложенного цикла
                    Ответить
                    • #include <iostream>
                       
                      int main()
                      {
                              do {
                                      std::cout << "start" << std::endl;
                       
                                      for (;;) {
                                              std::cout << "inner loop" << std::endl;
                                              break;
                                              break;
                                              break;  // сколько брейков должен написать Тарас, чтобы выйти из внешнего цикла?
                                      }
                                              
                                      std::cout << "still in one-pass loop" << std::endl;
                              } while (0);
                       
                              std::cout << "outside" << std::endl;
                       
                              return 0;
                      }

                      start
                      inner loop
                      still in one-pass loop
                      outside
                      Ответить
                      • Ну и не работает. Без гото никак, о чём я сразу и говорил.
                        Ответить
                        • ты собрался выделять ресурсы в цикле, чтобы потом из него выйти в случае ошибки через goto?
                          в любом случае, всё прекрасно будет работать без goto, если включить голову
                          int errc = result_ok, runlevel = init_nothing;
                          do {
                              errc = do_stuff1(...);
                              if (errc != result_ok) {
                                  log(errc, "stuff1 error");
                                  break;
                              }
                          
                              runlevel = init_stuff1;
                          
                              while (errc == result_ok && need_loop) {
                                  // tarasb supa inner loop stuff
                                 errc = do_uber_stuff(...);
                              }
                              if (errc != result_ok) {
                                  log(errc, "stuff2 uber error");
                                  break;
                              }
                          
                              runlevel = init_uber_stuff;
                          
                              errc = do_stuff3(...);
                              if (errc != result_ok) {
                                  log(errc, "stuff3 error");
                                  break;
                              }
                          
                              runlevel = init_stuff3;
                          } while (0);
                          
                          switch (runlevel) {
                              case init_stuff3:
                                  cleanup_stuff3(...);
                              case init_uber_stuff:
                                  cleanup_uber_stuff(...);
                              case init_stuff1:
                                  cleanup_stuff1(...);
                              default:
                                  ;
                          }
                          return errc;
                          Ответить
                          • Нет, для ресурсов я применяю РАИИ.
                            Выход из двойного цикла иногда нужен именно по алгоритму.
                            Ответить
                            • Предпочитаю писать goto или же рефакторить алгоритм так, чтобы не нужен был break из двух циклов (например, вместо этого break воспользоваться return, RAII этому только способствует).

                              Флагоебство не нужно, т.к. снижает и наглядность и производительность сильнее чем goto.
                              Ответить
                            • какой раии ты применяешь в С, расскажи-ка
                              Ответить
                              • Я С не применяю.
                                А выход из двойного цикла - проблема и в С++.
                                Ответить
                                • Да не особо и проблема. Зачастую имеет смысл отрефакторить внутренний цикл в функцию. Или же воспользоваться return вместо дабл\трипл\квадробряков.

                                  Скинь, пожалуйста, пример кода, в котором требуется даблбряк (полностью функцию), попробуем что-нибудь сделать с ним.
                                  Ответить
                                  • Да не могу я отрефакторить кусок кода в отдельную локальную функцию в этом блядском С++!!! А глобальная, нужная только в одном методе - это засорение пространства.
                                    Ответить
                                    • file scope недостаточно локален?
                                      Ответить
                                      • Да. Я не хочу, чтобы другие методы класса знали о существовании этой лишней функции.
                                        Ответить
                                        • > Да. Я не хочу, чтобы другие методы класса знали о существовании этой лишней функции.
                                          Убей их. Они слишком много знают.

                                          А если серьезно - если кроме методов класса никто не видит - это уже хорошо.
                                          Ответить
                                    • Ну на глобальную она не тянет - можно запилить на уровне файла или класса.

                                      Код в студию ;)
                                      Ответить
                                    • >cannot into отдельную локальную функцию в этом блядском С++
                                      Локальная функция:
                                      void f()
                                      {
                                        struct $ 
                                        {
                                          static void f()
                                          {
                                              ...
                                          }
                                          ...
                                          $::f()
                                          ...
                                        }
                                      - локальна на функцию.
                                      А также анонимный немспейс:
                                      namespace
                                      {
                                         void f()
                                        {
                                            ...
                                        }
                                      }
                                      ...
                                      f()
                                      ...
                                      - локальна на модуль cpp
                                      Ответить
                                      • Если извращаться - то по полной:
                                        http://ideone.com/TzUwa
                                        Ответить
                                      • Это будет и уродливо (лишний класс или пространство), и локальные переменные вызывающей процедуры придётся передавать всё равно явно.
                                        Ответить
                                    • > отдельную локальную функцию
                                      с++03 compartible:
                                      int main(void) {                            // Some local scope.
                                          int sum = 0, factor = 10;               // Variables in scope to bind.
                                      
                                          void BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) {
                                              sum += factor * num;
                                          } BOOST_LOCAL_FUNCTION_NAME(add)
                                      
                                          add(1);                                 // Call the local function.
                                          int nums[] = {2, 3};
                                          std::for_each(nums, nums + 2, add);     // Pass it to an algorithm.
                                      
                                          BOOST_TEST(sum == 60);                  // Assert final summation value.
                                          return boost::report_errors();
                                      }
                                      Ответить
                                      • Годно. Жду, когда выкатят релизную версию.
                                        Ты чего с аватарки фак показываешь или у виска крутишь?
                                        Ответить
                                      • Какой только пиздец не придумают, лишь бы не писать на нормальных языках, где это сделано из коробки и намного удобнее.
                                        Ответить
                                        • > писать на нормальных языках
                                          Ада?
                                          Ответить
                                        • в с++11 есть лямбды
                                          расслабься и жди поддержки стандарта
                                          Ответить
                                          • >расслабься и жди поддержки стандарта
                                            Расслабьтесь и попытайтесь получить удовольствие...
                                            Ответить
                              • Частный случай - atexit.
                                Ответить
                                • Ага. Для сервера, который крутится годами, at_exit это идеальное место для освобождения ресурсов.
                                  Ответить
                                  • 1)Я не сказал, что покрою все возможные случаи ракии. Даже указал, что это лишь частный случай.

                                    2)Настоящие сервера, крутящиеся годами (те что пишутся на си) - пишутся так, что каждый запрос обслуживается в отдельном процессе. Так что в atexit для освобождения части ресурсов самое время.
                                    Ответить
                                    • > пишутся так, что каждый запрос обслуживается в отдельном процессе.
                                      Не все. Иногда запросы мелкие и их много.
                                      Ответить
                                      • >Не все.
                                        Но тогда, они и годами не крутятся или очень простые или опять же пишутся годами.
                                        Ответить
                    • А двойной continue значит проскочит одну итерацию?
                      Ответить
                      • Всё вполне логично.
                        При множественном break; последующие просто не достигаются.
                        На первом же выскакивает из цикла, а остальные не у дел, как код после return;
                        И continue тоже не достигается. Как встретился, так цикл продолжился, а следующий не успевает исполниться.

                        Т.е. нужен какой-то дополнительный оператор. break в метку или break(<количество вложений>); как-то так.
                        Ответить
                        • Ка-пи-тан, капитан, улыбнитесь...
                          Вопрос был риторическим, как очередное доказательство неправильности суждений @TarasB о брэйках.
                          Ответить
                          • Ответ был мной дан для повышения количества комментариев. Ваш К.О.
                            Ответить
                            • Кармодрочер детектед. Тут же не форум с левелапами по количеству комментариев...
                              Ответить
                              • Это не ложка гнётся, всё дело в тебе.

                                Карма, она не на сервере, она в голове.
                                Ответить
                          • Какой неправильности? Я изначально привёл выход из двойного цикла как пример, где гото оправдано, назвав этой двойным брейком, я не думал ставить брек два раза, когда мне показали реально двойной брек, я сначала удивился, потом подумал, что в это язык встроили фичу для выхода из двойного цикла, потом понял, что это стёб
                            Ответить
                            • Ты говорил об этом так, и называл это так, что полностью создал впечатление, как будто ты искренне веришь в работу двух брейков подряд.
                              Ответить
                              • Если честно, это вышло случайно.
                                Хотя бывает и специально: http://www.gamedev.ru/code/forum/?id=139163
                                Ответить
              • Суть: goto хейтеры довольны.
                Ответить
      • Про C не могу сказать, потому что уже годы не касался совсем, но в С++ точно есть автоматические массивы.

        Разве что там какие-то ограничения на размещение в стеке, но тогда сразу должна была прийти мысль, о захвате ресурса другим, уже автоматическим объектом (да RAII).

        А тут мы видим, что люди шарашат динамическую память без понятия и компилятор не может им помочь избавиться от лишней работы по написанию delete[]. А если таких вычислительных функций не одна, а десять? Это же какой потенциал для ошибки!

        Такой код нужно студентам на лекции показывать :)
        Ответить
        • > в С++ точно есть автоматические массивы
          VLA? Они, конечно, удобны, но при невнимательности можно словить stack overflow.

          На выбор остаются векторы и scoped_ptr.

          > Такой код нужно студентам на лекции показывать :)
          Не стоит, выучат же.
          Ответить
        • >в С++ точно есть автоматические массивы

          Какой "автоматические массивы"? Поясните мысль.
          Ответить
          • Видимо, комментатор имеет ввиду std::array<CItem, N>, но ввиду динамичности N в исходной задаче - он не особо подходит.

            int arr[N] на стеке, как было в С, так в С++ этого точно нет. Если только какое то расширение компилятора.

            Ну и в случае POD-типов, как здесь, можно использовать alloca.
            В MS VS это _alloca и более правильная _malloca
            Сомневаюсь, что это часть стандарта (могу ошибаться), но вроде как поддерживается многими компилями.
            Ответить
          • Массив ссылочного типа с отложенным распределением.
            int arr[n];

            Для C++ это избыточно, но, тем не менее... Это, по крайней мере, уже указывает на то, что программист понимает, что семантика памяти должна быть автоматической. Хотя, всё равно, явные пробелы в познаниях std::
            Ответить
            • >int arr[n];

              Ниже уже рассказали, что C++ так не умеет.
              Ответить
              • От этого говногод не становится лучше.
                Александр Македонский тоже великий полководец, но зачем же стулья ломать?

                Зато C умеет, сказали ниже, значит можно отмести версию, что код выше -- это нормально для C.

                P.S. Вы не в ту сторону смотрите.
                Ответить
                • > Зато C умеет
                  И чем VLA помогут сделать этот код лучше? У вас есть гарантия, что n достаточно мало и мы не получим stack overflow?

                  VLA для массивов неконтролируемой длины это зло.
                  Ответить
        • > уже годы не касался совсем
          То есть вы мужчина
          >http://www.govnokod.ru/10569#comment143901
          Как бы это помягче спросить...
          Ответить
          • Ответ: да.
            Чтобы уж вам не спрашивать.
            Ответить
            • Значит, все эти слухи о программистах на c++ имеют под собой основания... о_О
              В виду последних эпичных тредов начал подумывать, не изучить ли c++ по человечески чтобы всех троллить. Но теперь вкрадываются сомнения, стоит ли....
              Ответить
              • Но это только слухи.
                Программистов на С++ гораздо больше. Так что не бойтесь. Изучайте.
                Вопрос в том... А нуно ли вам это? Занимаетесь ли вы такими вещами, что вам C++ нужен...
                Ответить
                • Меня интересуют в основном вопросы метапрограммирования, ибо цппшный подход к ООП сейчас распространён довольно широко и в целом хорошо понятен.

                  Несмотря на то, что метапрограммированию в с++ достаточно далеко от того, что можно делать в lisp, подходы всё равно интересны. Да и просто неприятно открывать продвинутый цппшный код и не понимать, что за неведомая х**ня там творится.

                  Конечно, гораздо больше интереса у меня вызывает функциональное программирование и большие распределённые высоконагруженные системы. Но мой жизненный опыт гласит, что для того, чтобы летать в облаках функциональщины, нужно уметь твёрдо стоять на грешной c/c++ земле. И если с C у меня особых проблем нет, то вот c++ код бывает непонятным довольно часто.
                  Ответить
                  • >ибо цппшный подход к ООП сейчас распространён довольно широко и в целом хорошо понятен

                    ромбовидное_наследование.cxx
                    Ответить
                    • Смотря что считать наследованием.
                      Ответить
                    • Тогда уж и friends.cxx туда же. Мне лично всё понятно и особых вопросов не возникает (в отличии от трёхэтажных шаблонов).
                      Ответить
      • Хотя, возможно, автоматические массивы в C++ -- это тоже неявный захват указателя из динамической памяти, а потом вызов удаления.

        В C++ вообще массивы C-style -- это нехорошо. Есть мощная и удобная стандартная библиотека.
        Ответить
        • Если мне не изменяет память, они всегда размещаются в стеке. Как простой int a[4], так и VLA в виде int a[n].
          Ответить
          • В стеке, значит в стеке.
            В C наличие таких массивов было бы действительно удобным, а в С++ уже избыточно. При такой-то необъятной стандартной библиотеке!

            >Не стоит, выучат же.
            Прально! Выучат, что это плохо. Будут пользовать std::
            Ответить
    • а чем плох вариант:
      float* x = new float[n];
      ...
      if (! /*validation*/ ) {
      float* y = new float[n];
      ...
      if (! /*validation*/ ) {
      ...
      }
      delete[] y;
      }
      delete[] x;
      зы. подразумевается работа без генерации исключений
      Ответить
      • > подразумевается работа без генерации исключений
        Для c++ именно этим и плох.

        Кстати, со scoped_ptr код короче, надежнее, понятнее и эквивалентен по производительности.
        Ответить
      • Вот так например:
        boost::scoped_array<float> x = new float[n];
        ...
        boost::scoped_array<float> y = new float[n];
        ...
        Ответить
      • Собственно, этот код не решает основную проблему: необходимость вызвать delete[] в определённом месте, хотя это разрешаемо на этапе компиляции.

        Вопрос не только в копипасте большого количества delete[], хотя, предложенный вариант, вне всяких сомнений легче отследить, но и в том, что "ручное" освобождение памяти не нужно. Память имеет автоматическую семантику: точно известно где и когда создать и точно известно, где и когда убрать. Пример, конечно, уж совсем тривиальный, потому что здесь даже не нужно выделять структурных блоков видимости, чтобы делегировать управление вставку вызовов работы с памятью компилятору.
        Ответить
        • > "ручное" освобождение памяти не нужно
          Нужно. В тех случаях когда скопы, деревья наследования и счетчики ссылок уже не спасают. Ну и, конечно, для реализации всех этих способов освобождения памяти.
          Ответить
          • Нет, нет.
            Я говорю, про "не нужно" в конкретном примере.

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

            Полагаю, такого не может произойти, что в коде образуется кусок памяти, который невозможно освободить. Существование сборщиков мусора говорит о том, что это возможно. Есть какой-нибудь 1% кода, когда это действительно затруднительно.
            Но может быть это просто наша ошибка? Может стоит пересмотреть пост-пред условия контрактов, как-то поменять весь алгоритм, чтобы стало проще? Может мы изначально выбрали неверное архитектурное исполнение?
            Здесь масса причин может быть.

            По крайней мере, существование сборщиков мусора в управляемых языках показывает, что уборка этого 1% может быть сделана. Причём, зная конкретно структуру свой программы, скорее всего, можно организовать это ещё более эффективно. И всего-то в одном случае из ста. Да и то, это я хватанул. Такие ситуации исчисляются сотыми долями процента и весьма специфичны, для них, наверняка, есть велосипеды.
            Ответить
    • This comment intentionally left blank
      Ответить
    • std::vector
      std::unique_ptr
      boost::scoped_array
      Ответить
    • Вот для этого в сишке с 99 года, а в Аде с 83 года и придумали массивы неизвестной при компиляции длины со стековой аллокацией. Бля, как же без них хуёво в дельфи и крестах... Приходится уродливые векторы лепить, кучу дёргать, фффуэ.
      Ответить
      • Они есть в крестах ;)
        Ответить
      • если бы тебе очень захотелось, то ты бы наверняка нашел библиотечную функцию alloca ;)
        Ответить
        • Кроссплатформенность?
          Ответить
          • как обычно
            #if defined (WIN32) ...

            тебе разве не достаточно
            http://msdn.microsoft.com/en-us/library/wb1s57t5.aspx
            http://www.kernel.org/doc/man-pages/online/pages/man3/alloca.3.html
            http://www.opennet.ru/man.shtml?topic=alloca&category=3&russia n=1 // freebsd
            Ответить
          • MSVC, gcc, на остальных не факт, в стандарте ее нет.
            Ответить
        • Так в с++ и VLA есть.

          Но они никому не нужны, т.к. можно без проблем создать класс, пользующийся alloca на мелких N и кучей на больших N. В этом случае имеем профит сопоставимый с VLA на мелких массивах, и не боимся вызвать stack overflow.

          P.S. А есть в бусте такой класс?
          Ответить
          • я о таком не знаю по крайней мере
            был в с++11 proposal о dynarray<T>, но вроде как его отклонили

            зы. в с++ VLA?
            Ответить
            • А вот прямо dynarray код приведён, хоть себе в проект тащи:
              http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2648.html
              Может в буст добавили.
              Ответить
              • именно о нем я и говорил, что отклонили
                внимательный зритель, кстати, заметит, что аллокация в этом dynarray делается по миссионерски - new char[ n*sizeof(T) ];

                фактически, несложно написать свой враппер над alloca, вызывая деструкторы объектов в массиве по выходу из scope, только стек всё равно освободится при выходе из функции
                Ответить
                • > аллокация в этом dynarray делается по миссионерски - new char[ n*sizeof(T) ];
                  Наверное, можно в тех случаях, где поддерживается alloca и n меньше некоторой величины (предлагаю размер страницы для платформ со страничной памятью), то выделяем через alloca на стеке.
                  Ответить
          • Что за VLA? Ссылка, пример? int arr[N] на стеке, то такого нет в стандарте.
            Ответить
            • variable length array
              Ответить
              • Нет такого в плюсах. Страуструп тогда уже С89 скопипастил в плюсы.
                > C (added in C99 as a conditional feature which implementations aren't required to support[1]; on some platforms
                Ответить
                • Ок, признаю свою ошибку, это ГЦЦизм, добавленный для совместимости с С.
                  Ответить
    • Посоны, а вектор при = копируется же, да?
      Ответить
      • std::vector - да.
        Ответить
        • А почему у него нет оператора привода к T*?
          При замене T[] на std::vector<T> приходится строки, содержащие
          T *t=a заменять на T*t=&a[0];
          Ответить
          • под "a" подразумевается вектор? О_о
            Ответить
          • > А почему у него нет оператора привода к T*?
            Потому что нехуй.

            > T*t=&a[0];
            Ужас какой. Можно узнать зачем все это?
            Ответить
            • Да хотя бы буфер заполнить значением. Или скопировать из вектора в видеобуфер
              Ответить
              • > Да хотя бы буфер заполнить значением.
                std::fill

                > скопировать из вектора в видеобуфер
                std::copy
                Ответить
                • Пройтись по буферу, чтобы фрагментарно скопировать на экран. А, да, итератор.

                  Кстати, как константныей итератор кастануть в неконстантный?
                  Ответить
                  • > как константныей итератор кастануть в неконстантный
                    Все-таки хочется выстрелить себе в ногу?
                    Ответить
                  • >Кстати, как константныей итератор кастануть в неконстантный?
                    А вы знаете толк в сортах говна...
                    Ответить
              • >из вектора в видеобуфер

                Вектор для хранения картинки плохо подходит: её размер известен и стоит использовать массив.
                Ответить
                • Нифига он не известен. (если ты про этам компиляции)
                  Ответить
              • Кстати если не секрет - а почему именно софтрендер? Почему бы, к примеру, не воспользоваться OpenGL? Даже банальные залитые полигоны оно рисует на порядки быстрее...
                Ответить
              • > скопировать из вектора в видеобуфер
                bitblt
                fastblt
                и тому подобное с аппаратной поддержкой блитинга из памяти в видеопамять
                Ответить
            • Чтобы передать массив в старую C библиотеку.
              Ответить
              • В с++11 появился метод data(). А так придется или как у тараса &a[0] или &a.front().
                Ответить
                • и оба, к сожалению, кинут пацана, если вектор пуст
                  Ответить
                  • Хм. Исключение судя по стандарту они кидать не должны. А результат, который они вернут, не имеет значения т.к. вменяемый программист не будет обращаться к элементам массива, который имеет размер 0.
                    Ответить
                    • и, действительно, не должны
                      я как то привык к студийному stl, что считал за должное - на &v[0] пустого вектора всегда жди беды
                      а это оказывается _SECURE_SCL мне так всегда подсирает

                      насчет вменяемого - как раз удобно передавать в сишные вызовы (..., &v[0], v.size(), ...), а там уже пускай библиотека в зависимости от size() пляшет
                      Ответить
                      • Когда я говорил про вменяемость я имел в виду именно обращение к элементам, а не передачу указателя.

                        А насчет передачи - ничего не имею против. Как я писал ниже "корректный код, зная, что ему передали указатель на массив длины 0 не будет его трогать".
                        Ответить
                  • А с чего бы вам получать адрес первого элемента пустого массива? о.о

                    Да ещё и пытаться передавать дырку от бублика куда-то там?
                    Ответить
                    • Передавать то можно. Но корректный код, зная, что ему передали указатель на массив длины 0 не будет его трогать.
                      Ответить
                      • Это, конечно, верно.
                        Но мне чаще встречались такие, которые требуют выполнения предусловий. Корректный указатель, положительное число и т.д.

                        P.S. Это может быть связано, конечно со сферой именно вычислительной. Функция сама не выполняет никаких проверок, потому что это может снизить производительность. Ведь неизвестно сколько раз её вызовут... 10 или 450 000.
                        Ответить
                        • > которые требуют выполнения предусловий
                          Проверки предусловий безусловно нужны. Но зачем проверять корректность указателя при size==0? И, кстати, как проверить корректность указателя в не managed куче?

                          > Функция сама не выполняет никаких проверок, потому что это может снизить производительность.
                          Я понимаю. Но допустим этой функции передали data=NULL и size==0. Зачем код будет трогать элементы data, если size==0. Можно пример? (Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0).
                          Ответить
                          • Например, нужно выполнить транспонирование матрицы.
                            Передаём два массива double in* double out* и два размера size_t n size_t m
                            Какой-то массив не определён и один из размеров равен нулю.
                            Функция не будет думать, что там что-то нулевое, а начнёт обращаться к элементам n*j + i. И будет бум!

                            Проверить на корректность указатель нельзя никак. Разве что dynamic_cast в некотором роде проверяет корректность указателя. А вообще никак. Операции передачи указателя всегда доверенные. Тот, кто передаёт, должен быть уверен в том, что указатель верный. Обыкновенно он уверен, потому что пред и пост условие содержит правило "указатель верный".
                            Ответить
                            • какая то каша
                              double const * in - только его и можно передать пустым
                              соответственно его размерности n и m будут в точности = 0, и циклы [0..n), [0..m) не сделают ни одной итерации
                              double * out - ну так он не имеет права быть меньше in

                              бум не случится
                              Ответить
                              • С чего это он не имеет права быть меньше in?

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

                                    Вы забыли инициализировать вектор.
                                    Ответить
                                    • >Вы забыли инициализировать вектор.
                                      Ок. Его size = 0. Вне зависимости от того что я передам в функцию - правильный указатель на пустой массив или любую хуйню - произойдет краш. Хотя в случае с правильным указателем он скорее всего не произойдет. Что еще хуже.
                                      Ответить
                                      • Да, конечно, будет креш. Потому что функции нужны данные, которые удовлетворяют предусловию: "два корректных массив размера: m*n >0 ? m*n : max(m,n);" Но функция этого проверить не может, да и не должна.
                                        Ответить
                                        • > два корректных массив размера: m*n >0 ? m*n : max(m,n)
                                          зачем ей max(m,n)
                                          обсуждается транспонирование?
                                          Ответить
                                          • Представим себе, что ноль и один определяет ковариантность столбца или строки.
                                            Ответить
                                          • Конечно, понятно, что m*n это вполне ясное представление, а все дополнительные чёрточки хорошо бы хранить отдельно.
                                            Но мне хотелось притянуть так, чтобы и ноль можно было записать.
                                            Ответить
                                            • Причем тут ноль. Строка - матрица 1*m, столбец - матрица n*1. Где тут 0?
                                              Ответить
                                              • Два типа матриц в программе. Матрицы типа 0*m и 1*m. 0*m -- это особая мнимая матрица.

                                                Bormand, успокойтесь. Понял уже я, что ты про другой ноль.

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

                                                Я просто поражаюсь тому, как умеют местные говорить не по делу.
                                                Ответить
                                                • > 0*m -- это особая мнимая матрица.

                                                  Хорошо. Пусть у нас будет особая, мнимая матрица 0*m. Если задача этого требует - пусть будет. Соответственно у этой матрицы нет элементов. Раз у нее нет элементов - лезть к ним нельзя. Иначе UB. Да и никто лезть не будет. Даже если, к примеру, у нас на входе матрица N*N, а на выходе получается (N-1)*(N-1) и N==1 (N==0, конечно, нельзя, выход за область определения). Поэтому я могу передать в качестве данных хоть мусор, хоть валидный указатель хоть NULL. Функция даже не заметит.
                                                  Ответить
                                                  • Так, Вольт, по-моему это серьёзно.

                                                    С чего это вдруг у мнимой матрицы нет элементов? Элементов у неё m, просто она мнимая.

                                                    И уже понятно, что речь шла о валидности предусловия size()==0. Просто по определению: если size()==0 функция на нулевом массиве должна достигать корректного постусловия. Следовательно, не может разименовать указатель, что приведёт к неопределённости. И потому не важно, что это за указатель.

                                                    Ясно
                                                    Ответить
                                                • > 0*m -- это особая мнимая матрица.
                                                  Кажется понял, к чему вы клоните - (0,m) и (n,0) специальные матрицы, у которых данные хранятся так же как и у матриц (1,m) и (n,1), но алгоритм обращается с ними по-другому? Но этот пример вообще не имеет отношения к "А с чего бы вам получать адрес первого элемента пустого массива?". Здесь массив не пуст (за исключением случая m==n==0), в нем есть max(m, n) элементов.
                                                  Ответить
                                        • Ну и ок. Только теперь прочитайте внимательно, что я просил привести в примере.
                                          Ответить
                                          • Понял к чему вы клоните.
                                            И тем не менее, пример наглядно показывает, что не всегда можно передать в функцию дырку от бублика и надеяться, что она её проглотит и сможет разрешить.
                                            Как я написал в своём комментарии: это хорошо, если может, но сам я с таким не сталкивался.
                                            Ответить
                                • Нет. В вашем примере нулевые размеры недопустимы. Программа работает не корректно не потому что в указателе мусор, а потому что size==0.
                                  Ответить
                                  • n и m -- это размеры матрицы. Размер массива: m*n>0 : m*n | max(m,n);
                                    Ответить
                            • > Какой-то массив не определён и один из размеров равен нулю.
                              Я же писал выше "Случай, если функция требует массив ненулевого размера отбрасываем, т.к. тогда ошибка не в том, что функции передали мусор в указателе, а в том что size==0"
                              Ответить
                            • > Функция не будет думать, что там что-то нулевое, а начнёт обращаться к элементам n*j + i. И будет бум!
                              И слава богу, если будет бум, а не вернется неведомая хуйня из неизвестной области памяти.
                              Ответить
      • >Посоны, а вектор при = копируется же, да?
        Так по С++11 копирования не будет, если аллокаторы совпадают. O(1)
        vector<int, int> a;
        a=f();

        Так тоже:
        vector<int, int> a, b;
        ...
        a=std::move(b);

        И так (но уже даже до стандарта С++11):
        vector<int, int> a, b;
        ...
        std::swap(a, b);
        Ответить
    • > И тем не менее, пример наглядно показывает, что не всегда можно передать в функцию дырку от бублика и надеяться, что она её проглотит и сможет разрешить.

      Рассмотрим все случаи, когда дырка от бублика не будет проглочена. (Пусть функция принимает массив переменной длины data и размер size).

      1) size == 0 не входит в область определения функции - имеем UB в любом случае, хоть в data дырка от бублика, хоть NULL хоть валидный указатель.

      2) size == 0, входит в область определения функции, но функция все равно лезет к элементам data. С вероятностью 146% в этой функции допущена ошибка, и она и при size>0 лезет за границы массива.

      3) size == 0 входит в область определения функции, функция не лезет к элементам data, но передает ее другой функции, которая к ним лезет - проблема рекурсивно сводится к первым двум пунктам.

      Во всех трех случаях UB присутствует независимо от того передам я туда NULL, валидный указатель или мусор. Причем валидный указатель только усугубляет проблему, и вместо краша программа может выдавать неправильный ответ.

      Поэтому спор о том, можно ли передать &a.front() (возвращающий NULL или мусор для пустого вектора) и a.size() в функцию считаю закрытым. Вердикт - можно.
      Ответить
      • Мой пример никак не связан с размером массива.
        В нём передаются корректные входные параметры скалярного типа и неверный указатель, проверить это невозможно. И получается бум!
        Он никак не связан с size()==0.
        Ответить
        • Типичный UB, порожденный вызывающей стороной ;) Проверить невозможно, согласен. Только соблюдать инварианты, и молиться, что их соблюдают все участники проекта.
          Ответить
    • Столько комментариев ниочем
      Ответить
    • Посоны, как передать локальный класс в параметр шаблона? Я не понимаю, почему этого нельзя, вель локальный класс не содержит никаких дополнительных неявных данных и отличается от глобального только зоной видимости, не?
      Ответить
      • template arguments must have external linkage, but local types have no linkage.
        Ответить
        • И чо делать?
          Ответить
          • выносить объявленный тип за пределы функции
            если беспокоишься за засорение пространства имён, попробуй обернуть в анонимный неймспейс

            14.3.1 Template type arguments
            2. A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall
            not be used as a template-argument for a template type-parameter. [Example:
            template <class T> class X { /* ... */ };
            void f()
            {
                struct S { /* ... */ };
                X<S> x3;  // error: local type used as template-argument
                X<S*> x4;  // error: pointer to local type used as template-argument
            }
            —end example] [Note: a template type argument may be an incomplete type (3.9). ]

            в с++11 кое-что могло поменяться по этому поводу
            Ответить
            • так и есть, в с++11 разрешили

              14.3.1 Template type arguments
              1 A template-argument for a template-parameter which is a type shall be a type-id.
              2 [ Example:
              template <class T> class X { };
              template <class T> void f(T t) { }
              struct { } unnamed_obj;
              void f() {
                  struct A { };
                  enum { e1 };
                  typedef struct { } B;
                  B b;
                  X<A> x1; // OK
                  X<A*> x2; // OK
                  X<B> x3; // OK
                  f(e1); // OK
                  f(unnamed_obj); // OK
                  f(b); // OK
              }
              — end example ] [ Note: A template type argument may be an incomplete type (3.9). — end note ]
              Ответить
              • Эх, херово...
                А как сделать такое?
                template <class T, T&t> void DoSmth() {}
                class A {};
                DoSmth<A, A()>(); // не OK, ссылка на созданный конструктором класс не считается константой времени компиляции
                DoSmth<A()>(); // couldnt deduce ошибка компиляции
                Ответить
                • что это?
                  ты хотел, может:
                  template <class T>
                  void do_smth(T & t = T()) {}
                  
                  do_smth<A>(); // ok
                  do_smth(A());// ok
                  Ответить
                  • гцц вот не согласен с передачей временного объекта как &
                    а студия всеядна
                    Ответить
                  • > do_smth(A());// ok
                    Да, мне это было надо (чтоб работало в т.ч. и для классов с конструктором с параметраме).


                    На const& я забил, оно вынуждает писать const в методах класса, просто & плюётся, что это типа нестандартное расширение, а классы, которые я буду у себя передавать, всё равно слишком мелкие, чтобы копирование со стека могло замедлить работу, да и оптимизации компилятора стопудов есть на этот случай.
                    Ответить
                    • подумай над целесообразностью передачи & вместо const &
                      вряд-ли тебе на самом деле нужно менять временный объект
                      Ответить
                      • 1. А вдруг?
                        2. Писать const во всех методах не хочу.

                        ПС поставил плюсик ^_^
                        Ответить
                        • 1,2 - гцц в обоих случаях скажет, что не ок, а с const & ок
                          ты уж определись, либо ты меняешь объект (тогда ломай голову над корректной передачей необязательного & - подсказка - аналог boost::optional, либо указатель вместо ссылки), либо ты просто к нему обращаешься за чтением - тогда временный объект const & по умолчанию вполне приемлем
                          Ответить
                          • Странно, студия на 4 уровне говорит, что всё нормально.
                            Ответить
                            • http://www.rsdn.ru/forum/cpp/2520038.hot.aspx
                              Ответить
                              • А, так я убрал =A() из параметров.
                                А передавать A() по копии кто мешает-то?

                                Ёпт, убрал расширения языка из опций, так он ругнулся на скачанный мной из инета stdint.h
                                c:\Users\TarasB\Documents\Visual Studio Projects\units\stdint.h(247): fatal error C1071: unexpected end of file found in comment
                                Ответить
                                • вечно ты всякое говно подбираешь
                                  Ответить
                                  • Так почему нельзя передавать свежесозданный экземпляр класса в функцию по копии?
                                    Ответить
                                    • Конечно же можно (строка 25):
                                      http://ideone.com/cKrSH
                                      Но нахуя?

                                      По & свежесозданный A(1) передавать нет никакого смысла (да и gcc не даст) - т.к. вызывающая функция все равно не сможет им воспользоваться. Если хочешь изменить в функции объект и воспользоваться результатом - опиши его как "A a(1);", а не создавай прямо в вызове.

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

                                      Свежесозданный объект имеет смысл передавать только по const &.
                                      Ответить
                                      • Не ссы, объект мне там нужен чисто для внутреннего пользования, деструктора и копира у него нету, данных внутри тоже.
                                        Так что раз можно, то збс
                                        Ответить
                                        • > данных внутри тоже
                                          Эээ, а зачем тогда передавать этот, хм, unit type, в функцию?
                                          Ответить
                                          • раз там нет данных, смею предположить, что все его методы должны быть статическими
                                            а, следовательно, нет никаких тарасо-проблем "ну там же надо const расставлять, а я крутой программист, мне это не нужно"
                                            Ответить
                                            • Ага, вот и я так думаю - если данных нет - кроме статических или "статических" (не описанных как статик но не юзающих this) методов ничего не запилить. А раз так - то этот объект не нужен.

                                              Другое дело - если в нем есть виртуальные методы, и Тарас хочет сделать что-то типа такого:
                                              http://ideone.com/Ezw24
                                              Ответить
                                              • в классе Greeting не то чтобы не было данных
                                                в любом случае, раз он собрался передавать как копию, он (вероятно) понимает, что base b = derived; сделает ему копию именно типа base и никакой полиморфизм тут уже работать не будет
                                                и да, где виртуальный деструктор, блеать?
                                                Ответить
                                                • > где виртуальный деструктор, блеать
                                                  Все, месяц каторжных работ на асме. Каюсь. (Хотя в этом примере деструкторы все равно отработают не виртуально).
                                                  Ответить
                                            • Статический метод или нет - без const этот класс никуда ты не передашь по const&, чтобы его можно было использовать.
                                              Ответить
                                              • > Статический метод или нет - без const этот класс никуда ты не передашь
                                                попробуй скажи статическому методу const, посмотрим, оценит ли компилятор шутку
                                                Ответить
                                                • А что помешает?
                                                  (на всякий случай - я про конст, говорящий о том, что метод не меняет данные объекта)
                                                  И какая разница, статический или динамический?
                                                  Ответить
                                                  • помешает то, что статический метод принадлежит классу, а не объекту
                                                    а для класса понятия const не существует
                                                    поэтому компилятор обязательно выдаст тебе ошибку
                                                    ну и, несложный вывод, что статический метод можно вызвать не только у константного объекта, но и вообще без объекта
                                                    Ответить
                                                    • А, я понял, о чём ты. Кстати, не всегда метод будет статический.
                                                      Ответить
                                                      • зачем объекту, у которого нет данных, по твоим словам, не статические методы?
                                                        Ответить
                                                        • Опять же, будут исключение, иногда этот объект таки будет содержать данные. Правда, для столь редкого случая уже не ломает написать const, да.
                                                          Ответить
                                                          • Ах ёпт, передача экземпляра класса без полей и со статическим методом выдаёт предупреждение что unreferenced formal parameter
                                                            Ответить
                                                            • Тарас, что ты там так усердно передаешь? Покажи уже код, рожденный в этих муках.
                                                              Ответить
                                                            • > unreferenced formal parameter
                                                              опять ты за старое
                                                              Ответить
                                                              • Ну ёпт, warn off это слишком по-крестоблядски, это не мой метод.
                                                                Ответить
                                                                • Код в студию. А вообще есть такой прием:
                                                                  int test(int unused) {
                                                                      (void)unused;
                                                                  }
                                                                  Ответить
                                                                  • > Код в студию
                                                                    не парься, он уже знает что делать
                                                                    Ответить
                                                                  • Я знаю про этот приём, даже если я и найду, куда это всобачить, это больше руками печатать, чем тупо передача по копии.
                                                                    А переголова из-за передачи неиспользуемого this в нестатическую функцию стопудов уберётся.
                                                                    Ответить
                                                            • Warnig level 4 - wall -wextra -pedantic -Werror ?
                                                              Ответить
                                                              • -Wall -Wall *стуча головой о стену* -Wall -Wall
                                                                Ответить
                                                              • -Wall -Wextra -Wformat=2 -pedantic -Winit-self -Wstrict-overflow=4 -Wcast-qual -Wcast-align -Werror

                                                                Удачной компиляции :-)
                                                                Ответить
                                                                • А что будет? Не даст скомпилить даже стандартные либы?
                                                                  Ответить
                                                                  • На первом попавшемся коде:

                                                                    main.c: В функции «evil_timeout»:
                                                                    main.c:89:24: ошибка: параметр «data» не используется [-Werror=unused-parameter]
                                                                    Ответить
                                                                    • Не люблю -Werror.

                                                                      Имхо лучше проявлять дисциплинированность, и в более-менее удобные моменты устранять ворнинги, нежели тратить время на бесполезный фикс ворнингов в коде, который минут через 10-15 будет выпилен нахрен или отрефакторен.
                                                                      Ответить
                                                                    • Ну с Werror понятно, а какие ещё сюрпризы будут?
                                                                      Ответить
                                                                      • Варнингов будет очень много
                                                                        Ответить
                                                                        • В хелоуворде?
                                                                          Ответить
                                                                        • Кстати gcc в этом плане, имхо, поумнее чем MSVC. Он игнорит ворнинги в системных хидерах.
                                                                          Ответить
                                                                          • А потому они в своём гццешном коде стандартной библиотеки их не исправляют, тк ни кто не пишет багрепорты?
                                                                            Ответить
                                                                            • Вы так говорите, как будто MS что-то исправляет. И, кстати, желающие слать багрепорты могут добавить себе флажок -Wsystem-headers что-ли.
                                                                              Ответить
                                                                        • Я понял, что будет много предупреждений по фигне, считающейся естественной, но всё-таки какие?
                                                                          Отсутствие переноса строки после {?
                                                                          };?
                                                                          Ответить
                                                                          • В основном касты в меньшие типы и сравнения signed и unsigned. Ну и unused variable.
                                                                            Ответить
                                                                            • Так это он и так на w4 предупреждает. Про неявные касты и сравнения в Аде это вообще не компилируется, пока явно не кастанёшь.
                                                                              Ответить
                                                                          • >отсутствие переноса
                                                                            я знаю ворнинг "файл обязан заканчиваться newline"
                                                                            на днях я так и не поборол его в гцц 3.x в новом проекте - везде где можно уже поставил, все равно где то у него не вяжется
                                                                            Ответить
                                                                            • Вот вам смешно, а в ГНАТе есть группа галочек, после включения которой тебе будут мыть мозги, что ты не так переменую назвал, не там скобочку поставил, слишком длинную линию написал итд.
                                                                              Я её не включаю правда.
                                                                              Ответить
                                                                              • > после включения которой тебе будут мыть мозги
                                                                                У нас в проекте есть Sonar, который занимается такой хернёй, и менеджмент заставляет нас фиксить "неправильно" названные переменные и слишком много условий в ифах. А то, что архитектура в жопе, и код надо рефакторить нахрен, это мало кого волнует.
                                                                                Ответить
                                                                                • на прошлой работе был настроен Sonar (или JSLint) вкупе с Bamboo, причем так, что continous integration билд сразу валился, если в жабаскрипте было написано что-то вроде
                                                                                  if(a)dosmth();
                                                                                  вместо
                                                                                  if(a){dosmth();}
                                                                                  "mixed tabs and spaces" тоже была фатальной ошибкой, ломающей билд.
                                                                                  помню, я тогда сильно матерился
                                                                                  Ответить
                                                                              • Будете смеяться, но я Eclipse (на работе) и Idea (дома) настроил (долго и вдумчиво) на максимальный в разумных пределах режим "Warnings and Errors" и "Inspections"+"Intentions", а еще на Eclipse повесил FindBugs, а также настроил форматирование кода при сохранении.
                                                                                И не успокаиваюсь, пока в коде есть warningи.
                                                                                Можете показывать на меня пальцами, но у меня при сохранении Eclipse не только форматирует код (да-да, мне лень все пробелы, табы выравнивать ручками), но и сам подставляет this. для полей и методов, а для неизменяемых переменных и полей сам пишет final.
                                                                                Ответить
                                                                                • Eclipse - говно
                                                                                  Ответить
                                                                                  • зато халявное. кстати, не он не так уж плох.
                                                                                    Ответить
                                                                                    • [holywarmode=on]
                                                                                      Кстати, пришлось тут поработать в VS 2008 с c# (помнится, студия - давняя гордость дотнетчиков), так вот, Idea мне кажется гораздо более удобной и стабильной (студия регулярно падает в дебаге). В VS по умолчанию даже дифф-тула нет, а плагины для того же свн тормозные и глючные. Походу всё работает до тех пор, пока всё идёт по плану мелкомягких (TFS и т.п.), шаг влево - вправо - расстрел, прыжок на месте - попытка улететь.

                                                                                      Без Resharper на VS вообще смотреть даже не хочется.
                                                                                      [/holywarmode]
                                                                                      Ответить
                                                                                  • > Eclipse - говно
                                                                                    Говно, но бесплатное и с кучей плагинов. Есть мнение, что IBM просто не способен на производство продуктов, которыми удобно пользоваться.
                                                                                    Ответить
                                                                                • > мне лень все пробелы, табы выравнивать ручками
                                                                                  Idea сама выравнивает, предлагает упрощать выражения и подсвечивает слишком сложные конструкции (try внутри цикла считает сложной, к примеру, но уж никак не 4 условия в ифе). Даже емакс выравнивает строчку при нажатии Enter или ввода точки с запятой (можно ещё таб нажать, если нужно форсировать выравнивание). Форматирование, кстати, Sonar не ловит, в коде полно вермишели из табов и пробелов.
                                                                                  Ответить
                                          • Ради метода. Ради одного метода.
                                            Ну нету в этом блядском С++ шаблонов, принимающий ФУНКЦИИ в качестве параметров. В Аде вот блин с 83 года есть, а в С++ нету. Поэтому приходится передавать класс.
                                            Ответить
                                            • > Ну нету в этом блядском С++ шаблонов, принимающий ФУНКЦИИ в качестве параметров.
                                              Так?

                                              http://ideone.com/RyeWm
                                              Ответить
                                              • Ты передал указатель, а не функцию.
                                                Компилятор хоть догадаться и заинлайнить сможет? Гарантируется ли?
                                                Ответить
                                                • Функции в с/c++ не first order типы, что означает, что их нельзя передавать. А можно только указатели на них.
                                                  Выхлоп гцц на О2:
                                                  movl    $13, 4(%esp)
                                                  movl    $_ZSt4cout, (%esp)
                                                  call    _ZNSolsEi
                                                  Ответить
                                            • в качестве параметра функции функцию умеет даже С
                                              зачем шаблониться?
                                              если ты хочешь передавать что-нибудь, что имеет operator (), то тебе нужно либо делать функторы (работает в голом с++03), либо boost::function (std::function)
                                              я не знаю что там умеет твой калеченный андроид ндк, но в принципе boost.function/boost.bind полностью инлайновый и должен работать
                                              Ответить
                                              • Затем, что мне нужно заинлайнивание этого параметра.
                                                Ответить
                                                • http://www.govnokod.ru/11308#comment144987
                                                  Тебе такого инлайна мало?!
                                                  Ответить
                                                  • > call _ZNSolsEi
                                                    Это не инлайн. Я не очень рублю АТТ синтаксис, но судя по отсутствию скобок, это прямой вызов, а не по указателю, и на том спасибо. Но это не то, что мне надо
                                                    Ответить
                                                    • > но судя по отсутствию скобок, это прямой вызов
                                                      Где ты тут вызов увидел. Гцц превратило std::cout << run<test>(5, 6) в тупо std::cout << 13. Что как бы намекает на инлайн через 2 колена.
                                                      Ответить
                                                      • call относится только к std::cout::operator <<?
                                                        Ответить
                                                        • вот тебе пример, как всё будет инлайниться даже без шаблонов
                                                          http://bit.ly/MZmirQ
                                                          компилятор оставил тела функций g и f, потому что они должны быть видны в объектнике
                                                          а вот более наглядно:
                                                          http://bit.ly/LUDOhz
                                                          Ответить
                                                        • > call относится только к std::cout::operator <<
                                                          Да. _ZNSolsEi вроде как он и есть.
                                                          Ответить
                                                        • Кстати забавно - попробовал без шаблона, тупой передачей указателя на функци, и с неконстантными параметрами - вместо 5 и 6 читал их с cin. g++ додумалось run(test, a, b) превратить в lea eax, [eax+edx+2], где в eax и edx лежали введенные значения.
                                                          Ответить
                    • > оно вынуждает писать const в методах класса
                      Вы так говорите, как будто это что-то плохое.
                      Ответить
                • > ссылка на созданный конструктором класс
                  Ссылка на созданный конструктором объект.

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

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