Russian Qt Forum
Апрель 24, 2024, 05:52 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало Форум WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  
  Просмотр сообщений
Страниц: 1 ... 114 115 [116] 117 118 ... 140
1726  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 14:57
Цитировать
и кто побеждает-то?
Получается весьма забавный результат: побеждает dynamic_cast  Непонимающий
Вот сам тест:
Код
C++ (Qt)
#include <iostream>
#include <list>
#include <ctime>
#include <cstdlib>
#include <cstdio>
 
using namespace std;
 
enum type_derived { TYPE_INT, TYPE_F };
 
class Base
{
public:
   Base() {}
   virtual ~Base() {}
   virtual void print() = 0;
   virtual type_derived type() const = 0;
};
 
class DerivedInt : public Base
{
public:
   DerivedInt(int id = 0) : m_id(id) {}
   void print() { /*cout << "DerivedInt, id = " << m_id << endl;*/ }
   type_derived type() const { return TYPE_INT; }
   void myFunc() { /*cout << "DerivedInt, id = " << m_id << endl;*/ } // not virtual
private:
   int m_id;
};
 
class DerivedF : public Base
{
public:
   DerivedF(float id = 0.0f) : m_id(id) {}
   void print() { /*cout << "DerivedF, id = " << m_id << endl;*/ }
   type_derived type() const { return TYPE_F; }
   void myFunc() { /*cout << "DerivedF, id = " << m_id << endl;*/ } // not virtual
private:
   float m_id;
};
 
typedef list<Base*> ListBase;
typedef list<Base*>::iterator Iter;
 
void generate(ListBase &l, size_t N) {
   for (size_t i = 0; i < N; ++i) {
       if (rand() % 2)
           l.push_back(new DerivedInt(i));
       else
           l.push_back(new DerivedF(float(i)));
   }
}
 
void clearList(ListBase &l) {
   for (Iter it = l.begin(); it != l.end(); ++it) {
       delete *it;
   }
   l.clear();
}
 
void test_dynamic_cast(ListBase &l) {
   Iter it = l.begin();
   for(; it != l.end(); ++it) {
       DerivedF *obj = dynamic_cast<DerivedF*>(*it);
       if (obj)
           obj->myFunc();
   }
}
 
void test_virtual_fun(ListBase &l) {
   Iter it = l.begin();
   for(; it != l.end(); ++it) {
       if ((*it)->type() == TYPE_F) {
           DerivedF *obj = static_cast<DerivedF*>(*it);
           obj->myFunc();
       }
   }
}
 
int main()
{
   ListBase lb;
   size_t Num = 20000000;
   srand(time(0));
   generate(lb, Num);
 
   clock_t tStart = clock();
   test_dynamic_cast(lb);
   //test_virtual_fun(lb);
   cout << (float)(clock() - tStart) / CLOCKS_PER_SEC << endl;
 
   clearList(lb);
   return 0;
}
 
Суть эксперимента такова:
Есть базовый класс Base с чисто виртуальными двумя функциями print() и type().
От него наследуются два класса DerivedInt и DerivedF в которых данные функции переопределяются.
Но также в этих классах я ввожу не виртуальные методы myFunc().
Далее создаётся список, содержащий указатели на базовый класс Base:
Код
C++ (Qt)
typedef list<Base*> ListBase;
typedef list<Base*>::iterator Iter;
 
   
И заполняется объектами на DerivedInt и DerivedF (случайным образом):
Код
C++ (Qt)
void generate(ListBase &l, size_t N) {
   for (size_t i = 0; i < N; ++i) {
       if (rand() % 2)
           l.push_back(new DerivedInt(i));
       else
           l.push_back(new DerivedF(float(i)));
   }
}
 
Затем проверяется вызовы dynamic_cast виртуальных функций:
Код
C++ (Qt)
void test_dynamic_cast(ListBase &l) {
   Iter it = l.begin();
   for(; it != l.end(); ++it) {
       DerivedF *obj = dynamic_cast<DerivedF*>(*it); // Один вызов dynamic_cast
       if (obj)
           obj->myFunc(); // один вызов не виртуального метода!
   }
}
 
void test_virtual_fun(ListBase &l) {
   Iter it = l.begin();
   for(; it != l.end(); ++it) {
       if ((*it)->type() == TYPE_F) { // Один вызов виртуального метода
           DerivedF *obj = static_cast<DerivedF*>(*it); // Пренебрегаем издержками на вызов static_cast
           obj->myFunc(); // один вызов не виртуального метода!
       }
   }
}
 
Думаю, что тест не совсем чист, поскольку я не учитываю издержки связанные с оператором static_cast
1727  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 14:17
Проверил сейчас, что быстрее работает: вызов виртуальной функции или dynamic_cast:
Разницы практически никакой нет, едва заметный эффект начинает появлятся только после миллиона вызовов.. Так что смысла в этой оптимизации, реально 0.
 
1728  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 20, 2011, 13:56
У меня тут ещё вопрос возник:
Корректно ли тогда будет такая конструкция работать:
Код
C++ (Qt)
class A
{
public:
   void func1() {}
   void func2() {}
};
 
void *addr1 = (void*)&A::func1;
void *addr2 = (void*)&A::func2;
 
if (addr1 != addr2)
...
elae
...
 
Непонимающий Или с указателями на функции такое уже не пройдёт?
1729  Qt / Общие вопросы / Re: Qt _ кириллица и ASCII : Март 19, 2011, 21:39

int simvol=(int)tt[0];


матюгаетцо:
invalid cast from type 'QCharRef' to type 'int'   

Код
C++ (Qt)
int symbol = (int)str[0].toAscii();
 

Хотя гораздо логичнее делать так:
Код
C++ (Qt)
QChar symbol = str[0];
QString answ=QString::number(simbol);
 
1730  Qt / Общие вопросы / Re: Qt _ кириллица и ASCII : Март 19, 2011, 21:21
да здесь по-моему проблема в другом:
Цитировать
Код
C++ (Qt)
QString tt;
int simvol;
QString answ;
tt="П";
simvol=tt.toInt();
answ=QString::number(simvol);
 
Как вообще можно требовать такое преобразование:
Код
C++ (Qt)
tt="П";
simvol=tt.toInt();
 
Непонимающий
Может быть так:
Код
C++ (Qt)
tt = "П";
int simvol=(int)tt[0];
QString answ=QString::number(simvol);
 
1731  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 21:10
Цитировать
Так что не верю я что можно написать "ну очень умный код" который уж наверняка будет совместим лет на 10 вперед. Если что случится - значит того не миновать, и нечего пытаться решать проблемы до их поступления

и

Цитировать
Сишный каст зло, потому что:
1. не имеет почти никаких ограничений (reinterpret_cast гораздо слабее), можно кастить тип, а заодно убить константность
2. трудно находится поиском
3. затуманивает смысл (не понятно, какой именно каст хотел сделать автор)

Ну конечно в таком простом примере сишный каст не страшен, но написать static_cast 1 раз не очень сложно, мне кажется. В вашем примере тоже странно выглядит, кстати: (char *) a == (char *) b, читающий на секунду задумается, почему именно char*, может это сравнение строк каких-то? Может в этих классах строки вначале? Может у них operator char * есть? Надо использовать void * для таких вещей. Когда код формально верный, то читается легче, перестаёшь всё время подозревать, что автор -- идиот.

== Мораль: Надо верить))
Хуже не будет)
1732  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 20:56
Цитировать
Не знаю. Можно иметь в базовом классе void * addr; и его сравнивать. Но тогда в наследниках придётся колдовать с кастами, думаю эта возня не стоит результата. Стоит ли вообще оптимизировать операцию connect? Она ведь редко выполняется, гораздо реже вызова слота.
Вот я тож об этом сейчас подумал.. Оно того стоит? Если по времени вызов виртуальной функции и вызов оператора dynamic_cast одного порядка то нефиг и суетится..

Цитировать
Вообще в C++0x предлагали ввести мультиметоды для ускорения подобных операций (не знаю, прошёл ли пропозал). Но до светлого будущего редко случается дожить..
Ну почему же) В gcc 4.5.1 уже практически полностью поддерживает стандарт C++0x на сколько мне известно) Гоаорят, что уже лямбды можно использовать)

Кстати, в libsig++ вообще не проверяется при создании нового соединения его наличие. Т.е. если подряд вызвать connect с одним и тем же слотом то слот будет повторно вызван  Грустный
1733  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 20:26
Цитировать
можно уменьшить и убыстрить так:
1. заменить size_t на void *
2. убрать у функции address атрибут virtual и =0
3. в теле address в базовом классе вернуть this (reinterpret_cast не нужен для преобразования в void*)
4. убрать address из наследников
1. Хорошо
2-4. так не получится по той причине, что мне не интересен адрес самого x_connection: я сравниваю адреса receiver, который является внутренней переменной соединения и содержит адрес объекта receiverА.    

Цитировать
надо иметь ввиду, что вызов dynamic_cast по скорости близок к вызову виртуальной функции, поэтому заменяя dynamic_cast на виртуальную функцию много не выиграешь.
Если так, то тогда получается, что нет смысла в этой оптимизации.  Грустный Непонимающий

1734  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 19:55
Собственно, вопрос возник в контексте оптимизации libssc.
Там ранее при создании нового соединения или, например, при записи приоритета соединения и т.п. каждый раз проверяется весь список соединений и каждый раз при этом вызывается dynamic_cast (который по природе своей не быстр). Вот чтобы избавится от лишних его вызовов, я ввёл в базовый класс (base_connection) виртуальный метод:
Код
C++ (Qt)
typedef size_t address_type // или typedef void* address_type или typedef char* address_type
...
virtual address_type address() const = 0;
 

И соответственно в унаследуемых классов этот метод определяю:
Код
C++ (Qt)
address_type address() const { return reinterpret_cast<address_type>(m_receiver); }
 
Это всё позволяет не вызывать лишний раз dynamic_cast в функции compre:
Код
C++ (Qt)
bool compare(base_connection2<S_arg1, S_arg2> *bc) const {
if ((bc->type() == MEM_FUN_CONNECTION) && (bc->address() == address())) {
   mem_fun_connection2<S_arg1, S_arg2, R_receiver, R_return, R_arg1, R_arg2> *mfc = dynamic_cast<mem_fun_connection2<S_arg1, S_arg2, R_receiver, R_return, R_arg1, R_arg2> *>(bc);
if (m_slot_is_const)
   return (mfc) ? (mfc->m_slot_pack.m_const_slot == m_slot_pack.m_const_slot) : false;
return (mfc) ? (mfc->m_slot_pack.m_slot == m_slot_pack.m_slot) : false;
}
return false;
   }
 
Собственно вот..
Спасибо)
1735  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 16:40
Я тут нашёл статейку о size_t и ptrdiff_t
http://www.realcoding.net/articles/chto-takoe-sizet-i-ptrdifft.html

В которой говориться, что в принципе проблем быть не должно, поскольку его (size_t) для этого и придумали, но есть исключение: это указатели на методы классов.
1736  Программирование / С/C++ / Re: тип size_t и сравнение указателей : Март 19, 2011, 16:08
Т.е. корректно ли это будет всегда и везде работать? И есть ли какие-нить грабли?
 Непонимающий
Не хочется делать обязывающих заявлений, но да, всегда. Практичнее/приятнее привести к (char *) вместо size_t
Спасибо)) Прям камень с души)
А в чём приимущество приведения к (char*) по сравнению size_t?
1737  Программирование / С/C++ / тип size_t и сравнение указателей : Март 19, 2011, 15:50
Приветствую)

У меня такой вопрос:
Имеется два указателя на объекты двух разных типов (A и B).
Хотелось бы сравнивать не сами указатели, а их значения приведённые к типу size_t.
Вот пример:
Код
C++ (Qt)
class A {
...
};
 
class B {
...
};
 
A *a = new A;
B *b = new B;
 
size_t address_a = reinterpret_cast<size_t>(a);
size_t address_b = reinterpret_cast<size_t>(b);
 
if (address_a != address_b)
   ....
else
   ....
 
 
Т.е. корректно ли это будет всегда и везде работать? И есть ли какие-нить грабли?
 Непонимающий
1738  Qt / Общие вопросы / Re: Вопрос по консольной программе(не решено) : Март 19, 2011, 13:39
m_ax
В цикле идет опрос серверов и в stdout выводится информация об опросе.
Заканчивается работа по команде с консоли exit.
Проблема в том, что команда readln переводит приложение в режим ожидания и прекращает работу основной функции Обеспокоенный
Фактически моя задача очень похожа на вашу. У меня есть ядро, которое занимается вычислениями (очень долгими и нудными), но я могу с консоли не прирывая вычисления вводить команды, например, для вывода статуса, остановки вычислений, перезапуска и ещё кучу всяких команд.
Ядро просто запускается в отдельном потоке, тогда readln не буде блокировать ядро.
Могу показать исходники самого механизма, реализующего само консольное приложения и механизм общения через консоль с объектами. 
1739  Qt / Общие вопросы / Re: Вопрос по консольной программе(не решено) : Март 19, 2011, 12:54
Может проще сделать как-то так:
Код
C++ (Qt)
std::string msg;
std::string quitCommand = "Exit";
while (true) {
       std::getline(std::cin, msg);
       if (msg == quitCommand) {
           quit();
           return 0;
       }
       sendEvent(msg);
   }
 
Или опишите проблему более детально, а то так очень смутно представляется что вы хотите..
Я сейчас тож пишу одно консольное приложение просто..
1740  Qt / 2D и 3D графика / Re: оптимизация paint() QGraphicsItem'а : Март 18, 2011, 22:05
Хм..
Цитировать
Код
C++ (Qt)
void PolarAxis::paint(QPainter *p, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
   p->setMatrix(scale_matrix);
   p->drawEllipse(x-rad,y-rad,rad*2,rad*2);
   p->drawLine(x,y,x,y-rad);
 
   QPen *dotPen=new QPen(Qt::DashDotLine); // Зачем?
   dotPen->setWidthF(0.3);
   QVector<qreal> dashes;
   dashes <<10 <<10;
   dotPen->setDashPattern(dashes);
   p->setPen(*dotPen);
 
   for (int i=rad-15;i>0;i-=15)
        p->drawEllipse(x-i,y-i,i*2,i*2);
        for (int i=0; i>-360; i-=10){
            p->drawLine(x,y,x+rad*cos(i*pi/180),y+rad*sin(i*pi/180));
            double x2=x+(rad+20)*cos(i*pi/180+90*pi/180+rotate*pi/180)-15;
            double y2=y+(rad+20)*sin(i*pi/180+90*pi/180+rotate*pi/180)-7.5;
            p->drawText(x2,y2,30,15,Qt::AlignCenter,QString("%1").arg(abs(i)));
        }
}
 
Во-первых зачем создавать dotPen в куче?
Во-вторых из-за него у вас утечка, поскольку не видно где он уничтожается
В-третьих
Цитировать
Код
C++ (Qt)
void PolarPlot::resizeEvent(QResizeEvent *re)
{
       QRect *rct=new QRect(0,0,re->size().height()-25,re->size().width()-25); // Те же грабли
       plotScene->setSceneRect(*rct);
       double h1=re->size().height();
       double h2=re->oldSize().height();
       double koef=h1/h2;
       pa->rescale(koef);   //в pa объект класса PolarAxis
 
}
 
всё сказанное выше, но приминительно к rct

А теперь представте, что будет при интенсивном ресайзе и отрисовки..
Страниц: 1 ... 114 115 [116] 117 118 ... 140

Страница сгенерирована за 0.455 секунд. Запросов: 24.