LINUX.ORG.RU

[C/C++/...][KDevelop] В продолжение разговора о int *i и int* i; int &i и int& i

 


0

1

Я так понял, большинство здесь таки придерживается стиля K&R, то есть прилепляет «*» и «&» к названиям переменных. Я тоже.

Замечательный astyle имеет параметр «--align-pointer» с возможными значениями type/middle/name.

А вот KDevelop в модуле переформатирования кода вообще не поддерживает эту фичу, то есть не трогает «*» и «&» и указателях и ссылках. Но вот при авто-дополнении всегда прилепляет эти значки в стиле Страуструпа, то есть к типу.

Кому не нравится это поведение, просьба проголосовать в https://bugs.kde.org/show_bug.cgi?id=263834.

★★★★★

Последнее исправление: Obey-Kun (всего исправлений: 1)
Ответ на: комментарий от aho

> просто ради интереса, как бы сделали вы в данном месте? чтоб и быстро и красиво
Ну, или хотя бы указатели на функции и их массив или еще что, отображающее mID в соответствующую функцию.

anonymous
()
Ответ на: комментарий от anonymous

> Виртуальные функции и наследование во все поля?

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

aho
()
Ответ на: комментарий от anonymous

Зато более красивое.

достаточно спорное утверждение, что-то вроде:

func[ kCmdAssign ] = &Command::DoAssign;
...
return ( this->*( func[ id ] ) )();

может и выглядит более круто чем

case kCmdAssign      : return DoAssign();

но врядли красивее

aho
()
Ответ на: комментарий от aho
class ICmd{
   virtual bool Execute() = 0;
};
//...

class DoAssign: ICmd{
   //...
   virtual bool Execute();
}
//....
class DoCloseCursor: ICmd{
   //...
   virtual bool Execute();
}
//...

ICmd* p = new DoAssign(/* ... */);
ICmd* p = new DoCloseCursor(/* ... */);

//...

void aPointWhereWeCallAnUncertainCommand(ICmd *pCmd){
//....
   pCmd->Execute();
}

Как-то так. Кстати, это стандартный код для демонстрации концепции полиморфизма (помните же байку о том, как нарисовать квадрат, круг и треугольник не зная что же конкретно нам нужно нарисовать?).

gandjubas
()
Ответ на: комментарий от aho

> ну и на скорость это бы повлияло в отрицательную сторону

Щито!?

Да у вас свитч - это и есть то самое место, которое будет влиять на скорость. (хорошо, может и не сейчас, а когда команд будет 20, к примеру)

Одним словом man виртуальные функции.

Если два разименования адреса для вас слишком много - используйте указатели на функции.

gandjubas
()
Ответ на: комментарий от aho

> пришлось бы создать много классов и файлов

Великолепный аргумент. Тогда уж запихните всё в одну функцию, зачем вам эти классы? Будет один файл - очень компактно.

gandjubas
()
Ответ на: комментарий от gandjubas

> хорошо, может и не сейчас, а когда команд будет 20, к примеру

их не будет 20, это базовый набор, на котором все и так работает

используйте указатели на функции


и что это даст?

Тогда уж запихните всё в одну функцию, зачем вам эти классы?


кажется вы не совсем вменяемы :) вы прекрасно видите, что по классам я разбиваю код, ну и по вашему интерфейсу - он явно недостаточен, вам надо будет вынести еще один базовый класс, где будет все то, что вы «не заметили», итого вместо двух файлов .h/.cpp на 300 строк в сумме ( из них большая часть не кода ) вы собираетесь завести больше 20 файлов, которые, да, дадут более медленный код

aho
()
Ответ на: комментарий от gandjubas

> Да вы, батенька, вообще не в теме

ну да - чтоб разнести пару сотен строк статичного кода на пару десятков файлов и кучу классов надо быть обязательно в теме

aho
()
Ответ на: комментарий от aho

> их не будет 20, это базовый набор, на котором все и так работает

Когда я сказал - может и не сейчас, я имел в виду то, что вы этого не заметите. Фактически же в вашем коде - уродская и затратная реализация косвенной адресации.

кажется вы не совсем вменяемы :)

Зато имею ЧЮ :)

gandjubas
()
Ответ на: комментарий от aho

А вы как хотели?

Спасает только одно - грамотная конценция именования файлов/объектов/нэймспейсов.

Опять же вложенные классы тоже никто не отменял.

Творите!

gandjubas
()
Ответ на: комментарий от gandjubas

> Фактически же в вашем коде - уродская и затратная реализация косвенной адресации.

один switch на 9 элементов в одном методе будет наверняка быстрее вызова всех виртуальных методов через интерфейс, если б этому классу надо было еще расширятся - я бы ввел тут интерфейс, но он абсолютно статичный, тут не будет ничего нового

aho
()
Ответ на: комментарий от gandjubas

> Творите!

обязательно, но с оглядкой на здравый разум :)

aho
()
Ответ на: комментарий от gandjubas

А и не забудте к перебору прибавить вызов функции-обёртки.

gandjubas
()
Ответ на: комментарий от gandjubas

> 2 операции vs перебор со сравнением по 9 элементам (в среднем - 4-м)? Ню-ню.

а вы обратите внимание на остальные методы этого класса, или их вы не вынесете в интерфейс? тогда как-то некрасиво получится ;) либо кастить - что медленно, либо использовать интерфейс совместно с базовой реализацией( коя должна быть и так, но по хорошему прикрыта ), что сводит на нет всю красоту от интерфейсов

aho
()
Ответ на: комментарий от aho

Вы не знаете языка, на котором пишете, но я не буду вас разубеждать. Продолжайте! И побольше пафоса о красоте и компактности кода (а главное - вранья о его скорости).

gandjubas
()
Ответ на: комментарий от gandjubas

> Вы не знаете языка, на котором пишете, но я не буду вас разубеждать

ес-но

И побольше пафоса о красоте и компактности кода


это не пафос - это объективная реальность, 300 строк в двух файлах лучше чем 18 файлов на «наследников», один на интерфейс и 2 на базовую реализацию

а главное - вранья о его скорости


не вопрос - код у вас, переписывайте на интерфейсы и давайте сравним, это просто, а пока вы просто клоуничаете

aho
()
Ответ на: комментарий от gandjubas

хотя знаете - да, я не прав, в Parse.cpp на 700 строк есть switch на 27!!! элементов, и даже если мы предположим, что компилятор расставит проверки так, чтоб делить case на равные( по возможности ) части, и что в данном случае это явно не узкое место, все-равно лучше разбить этот один файл на 54 файла .h/.cpp, плюс еще 20 файлов из Command.cpp и суммарные ужасные 1000 строк в 3 файлах( + сколько-там в Parse.h ) превращаются в 18 + 1 + 2 + 52 + 1 + 2 - всего навсего 76 файлов, вот это правильный подход к написанию кода

aho
()
Ответ на: комментарий от aho

Поздняк метаться, я уже тест накатал.


s3r_rea@ararat:~/c/test1> ls
t.c
s3r_rea@ararat:~/c/test1> cat t.c
#include <stdio.h>
#include <sys/time.h>

static int G_i=0;

typedef void (*cmd)();

void cmd1(){ G_i += 1; }
void cmd2(){ G_i -= 1; }
void cmd3(){ G_i += 2; }
void cmd4(){ G_i -= 2; }
void cmd5(){ G_i += 3; }
void cmd6(){ G_i -= 3; }
void cmd7(){ G_i += 4; }
void cmd8(){ G_i -= 4; }
void cmd9(){ G_i += 1; }

static cmd  aCmd[] = {&cmd1, &cmd2, &cmd3, &cmd4, &cmd5, &cmd6, &cmd7, &cmd8, &cmd9 };

void LOX(int i){
        switch(i){
         case 1: cmd1(); break;
         case 2: cmd2(); break;
         case 3: cmd3(); break;
         case 4: cmd4(); break;
         case 5: cmd5(); break;
         case 6: cmd6(); break;
         case 7: cmd7(); break;
         case 8: cmd8(); break;
         case 9: cmd9(); break;
         default: break;
        }
}

long long getMS(const struct timeval *start, const struct timeval *end){
  long long seconds, useconds;

  seconds  = end->tv_sec  - start->tv_sec;
  useconds = end->tv_usec - start->tv_usec;

  return ((seconds) * 1000 + useconds/1000.0) + 0.5;
}

int main(){
        struct timeval start, end;
        long long mtime;

        int i, j, Max = 10000000;

        printf("LOX is testing...\n");
        gettimeofday(&start, NULL);
        for(i=0; i < Max; i++)
                for(j = 0; j < 9; j++)
                        LOX(j+1);
        gettimeofday(&end, NULL);
        printf("Time: %lld ms. \n\n",  getMS(&start, &end));


        printf("FP array is testing...\n ");
        gettimeofday(&start, NULL);
        for(i=0; i < Max; i++)
         for(j = 0; j < 9; j++)
           (*(aCmd + j))();
        gettimeofday(&end, NULL);
        printf("Time: %lld ms. \n\n",  getMS(&start, &end));

        return 0;
}
s3r_rea@ararat:~/c/test1> gcc t.c
s3r_rea@ararat:~/c/test1> ls
a.out  t.c
s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 991 ms.

FP array is testing...
 Time: 549 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 995 ms.

FP array is testing...
 Time: 429 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 1312 ms.

FP array is testing...
 Time: 1175 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 944 ms.

FP array is testing...
 Time: 565 ms.

s3r_rea@ararat:~/c/test1>

gandjubas
()
Ответ на: комментарий от gandjubas

> Поздняк метаться, я уже тест накатал.

спасибо - поржал (с) включите оптимизацию и прозрейте насколько вы умеете правильно писать тесты, кстати то что вы таки привели в пример не интерфейсы - очевидно говорит, что и тут вы облажались

aho
()
Ответ на: комментарий от aho

s3r_rea@ararat:~/c/test1> gcc t.c -O3
s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 165 ms.

FP array is testing...
 Time: 188 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 224 ms.

FP array is testing...
 Time: 191 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 330 ms.

FP array is testing...
 Time: 213 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 327 ms.

FP array is testing...
 Time: 188 ms.

s3r_rea@ararat:~/c/test1>

gandjubas
()
Ответ на: комментарий от aho

s3r_rea@ararat:~/c/test1> gcc t.c -O2
s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 530 ms.

FP array is testing...
 Time: 292 ms.

s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
Time: 518 ms.

FP array is testing...
 Time: 289 ms.

gandjubas
()
Ответ на: комментарий от aho

s3r_rea@ararat:~/c/test1> gcc --version
gcc (GCC) 4.1.2 20070115 (SUSE Linux)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gandjubas
()
Ответ на: комментарий от gandjubas

gcc (GCC) 4.1.2 20070115 (SUSE Linux)

«gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5)»

специально поставил 4.1:

igor@igor-desktop:~$ gcc-4.1 -O3 ./1.c
igor@igor-desktop:~$ ./a.out 
LOX is testing...
Time: 94 ms. 

FP array is testing...
 Time: 154 ms. 
aho
()
Ответ на: комментарий от gandjubas
s3r_rea@ararat:~/c/test1> gcc t.c -O3
s3r_rea@ararat:~/c/test1> ./a.out
LOX is testing...
G_i: 10029202
Time: 2974 ms.

FP array is testing...
 G_i: 20027413
Time: 3026 ms.

s3r_rea@ararat:~/c/test1> cat t.c
#include <stdio.h>
#include <sys/time.h>
#include <stdlib.h>
#include <time.h>

static int G_i=0;

typedef void (*cmd)();

void cmd1(){ G_i += 1; }
void cmd2(){ G_i -= 1; }
void cmd3(){ G_i += 2; }
void cmd4(){ G_i -= 2; }
void cmd5(){ G_i += 3; }
void cmd6(){ G_i -= 3; }
void cmd7(){ G_i += 4; }
void cmd8(){ G_i -= 4; }
void cmd9(){ G_i += 1; }

void cmd11(){ G_i += 1; }
void cmd12(){ G_i -= 1; }
void cmd13(){ G_i += 2; }
void cmd14(){ G_i -= 2; }
void cmd15(){ G_i += 3; }
void cmd16(){ G_i -= 3; }
void cmd17(){ G_i += 4; }
void cmd18(){ G_i -= 4; }
void cmd19(){ G_i += 1; }


static cmd  aCmd[] = {
&cmd1, &cmd2, &cmd3, &cmd4, &cmd5, &cmd6, &cmd7, &cmd8, &cmd9,
&cmd11, &cmd12, &cmd13, &cmd14, &cmd15, &cmd16, &cmd17, &cmd18, &cmd19
 };

void LOX(int i){
        switch(i){
    case 0: cmd1(); break;
    case 1: cmd2(); break;
    case 2: cmd3(); break;
    case 3: cmd4(); break;
    case 4: cmd5(); break;
    case 5: cmd6(); break;
    case 6: cmd7(); break;
    case 7: cmd8(); break;
    case 8: cmd9(); break;
    case 9: cmd11(); break;
    case 10: cmd12(); break;
    case 11: cmd13(); break;
    case 12: cmd14(); break;
    case 13: cmd15(); break;
    case 14: cmd16(); break;
    case 15: cmd17(); break;
    case 16: cmd18(); break;
    case 17: cmd19(); break;
    default: break;
        }
}

long long getMS(const struct timeval *start, const struct timeval *end){
  long long seconds, useconds;

  seconds  = end->tv_sec  - start->tv_sec;
  useconds = end->tv_usec - start->tv_usec;

  return ((seconds) * 1000 + useconds/1000.0) + 0.5;
}


int main(){
  struct timeval start, end;
  long long mtime;
  srand (time (NULL));
    int i, j, Max = 10000000;

  printf("LOX is testing...\n");
  gettimeofday(&start, NULL);
  for(i=0; i < Max; i++)
    for(j = 0; j < 9; j++)
       LOX(rand () % 18);
  gettimeofday(&end, NULL);
  printf("G_i: %d \n", G_i);
  printf("Time: %lld ms. \n\n",  getMS(&start, &end));


  printf("FP array is testing...\n ");
  gettimeofday(&start, NULL);
  for(i=0; i < Max; i++)
    for(j = 0; j < 9; j++)
      (*(aCmd + (rand () % 18)))();
  gettimeofday(&end, NULL);
  printf("G_i: %d \n", G_i);
  printf("Time: %lld ms. \n\n",  getMS(&start, &end));

  return 0;
}
s3r_rea@ararat:~/c/test1> ls
a.out  t.c
s3r_rea@ararat:~/c/test1>

Так что же получается, не тому нас в школе учат?

Или я опять в тесте накосячил?

Кто подскажет?

/me в шоке

gandjubas
()
Ответ на: комментарий от gandjubas
        switch(i){
    case 0: cmd1(); break;
    case 1: cmd2(); break;
    case 2: cmd3(); break;
    case 3: cmd4(); break;
    case 4: cmd5(); break;
    case 5: cmd6(); break;
    case 6: cmd7(); break;
    case 7: cmd8(); break;
    case 8: cmd9(); break;
    case 9: cmd11(); break;
    case 10: cmd12(); break;
    case 11: cmd13(); break;
    case 12: cmd14(); break;
    case 13: cmd15(); break;
    case 14: cmd16(); break;
    case 15: cmd17(); break;
    case 16: cmd18(); break;
    case 17: cmd19(); break;
    default: break;
        }

Если бы функции cmd_i были радикально разными, проще было бы сделать массив указателей на функции, а этот ужас переписать как cmd() :)

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от gandjubas

Упс. До конца код не дочитал. Да уж, фигня какая-то выходит... Думаю, во всем виноват -O3. Без него наверняка switch был бы намного медленнее...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

> Исходя из теста gandjubas'а, выходит, что все-таки монструозная конструкция еще не означает уменьшение времени выполнения...

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

aho
()
Ответ на: комментарий от aho

Все-таки, ужас: тупой перебор выходит быстрее обращения по указателям аж на 30%! Вот и думай потом, как оптимизировать обработку с изображениями (где сплошь и рядом - указатели)...

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

> тупой перебор выходит быстрее обращения по указателям аж на 30%!

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

Вот и думай потом, как оптимизировать обработку с изображениями (где сплошь и рядом - указатели)


там указатели немного по другому используются

П.С. ну и да - по-моему зря я тогда сказал про скорость :) данный выбор switch vs ptrs практически не повлияет на суммарную скорость работы программы

aho
()
Ответ на: комментарий от Eddy_Em

Да не, нормально всё. Компилятор по ходу дела жульничает и конвертит свич в те самые указатели + оптимизирует ещё исходя из простоты тел функций, см. также ветку http://www.linux.org.ru/forum/development/5821449 - там выяснили, что на более сложных функциях switch и массив указателей эквивалентны. Что впринципе логично, если бы я реализовывал компилятор, я бы в общем случае так и делал - конвертил бы свичи в массивы указателей.

gandjubas
()
Ответ на: комментарий от dt1

> это плохой стиль, так нельзя писать

Про плохой стиль согласен, а писать так язык не запрещает )))

anonymous
()
Ответ на: комментарий от anonymous

> Про плохой стиль согласен, а писать так язык не запрещает )))

недостаток языка - плохой аргумент :P

dt1 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.