LINUX.ORG.RU

[Qt4] Вопросы по QList


0

0

С контейнерами и шаблонами еще не имел дела, так что помогайте.

1. Есть мой класс Curve;
   Как наполнить контейнер QList<Curve> ?
    
   ...
   QList<Curve> list;
   list.append(<X>); // что писать вместо "<X>"?
   ...

2. Есть указатеь на контейней;
   Я передаю его как параметр некоему объекту;
   Теперь нужно в объекте достать из i-го элемента public свойство

   ...
   QList<Curve> *list;
   ... <наполняем list> ...
   obj = new Class(list);
   ...

   Реализация класса Class:
   ...
   curvesList = list;
   int i = 9;
   int prop = ((*list)[i]).property; // выглядит очень криво, как правильно?
   ...

В результате этих синтаксических эксперементов (вопросы 1,2) у меня
либо сегфолты (неправильно наполняю, считываю элементы) либо ошибки
компилятора (неправильно записаваю выражения наполнения, считывания).

Помогите пожалуйста!

1.
Curve jopa;
Qlist<Curve> list;
list.append(jopa);

2. Вроде всё правильно написано. Иначе можно записать так:
int prop = list->operator[](i).property;
Только вот сомневаюсь, что будет красивее и понятнее :)

gaa ★★
()
Ответ на: комментарий от Delay

Теперь проперти достается (в конструкторе Class), но программа падает (аварийный останов), с примерно таким содержанием:

*** glibc detected *** ./geom_mod_3: double free or corruption (!prev): 0x08074518 ***
======= Backtrace: =========
/lib/i686/cmov/libc.so.6[0xb746c735]
/lib/i686/cmov/libc.so.6(cfree+0x90)[0xb74701a0]
/usr/lib/libstdc++.so.6(_ZdlPv+0x21)[0xb7634e41]
./geom_mod_3(_ZN7QWidget5eventEP6QEvent+0xbd8)[0x804ac7c]
./geom_mod_3(_ZN7QWidget5eventEP6QEvent+0x67f)[0x804a723]
./geom_mod_3[0x804b5ab]
./geom_mod_3[0x804b181]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe0)[0xb7417450]
./geom_mod_3(_ZNK7QWidget6metricEN12QPaintDevice17PaintDeviceMetricE+0x8d)[0x80
4a201]
======= Memory map: ========
08048000-0804d000 r-xp 00000000 08:05 618977     /home/fifajan/projects/kurs_41/geom_mod_3/geom_mod_3
0804d000-0804e000 rw-p 00004000 08:05 618977     /home/fifajan/projects/kurs_41/geom_mod_3/geom_mod_3


       ...


7b235637f494d515247eddd-x86.cache-2
b7f0f000-b7f12000 r--s 00000000 08:09 621090     /var/cache/fontconfig/6330322105e0c4105d7c7a6ea2974107-x86.cache-2
b7f12000-b7f14000 r-xp 00000000 08:09 1324405    /usr/lib/gconv/UTF-16.so
b7f14000-b7f16000 rw-p 00001000 08:09 1324405    /usr/lib/gconv/UTF-16.so
b7f16000-b7f1d000 r--s 00000000 08:09 1307363    /usr/lib/gconv/gconv-modules.cache
b7f1d000-b7f1f000 rw-p b7f1d000 00:00 0 
b7f1f000-b7f3b000 r-xp 00000000 08:09 1093564    /lib/ld-2.7.so
b7f3b000-b7f3d000 rw-p 0001b000 08:09 1093564    /lib/ld-2.7.so
bfcc7000-bfcdd000 rw-p bfcc7000 00:00 0          [stack]
ffffe000-fffff000 r-xp 00000000 00:00 0          [vdso]
Аварийный останов

Это из-зи использования QList.
Падает сразу, даже окно не успевает создать...

Почему такое может быть?

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

код покажи, только покороче.

ЗЫ сколько элементов в загоняешь QList ?

alex_custov ★★★★★
()
Ответ на: комментарий от gaa

Этой ошибки уже нет, теперь новая.

Есть класс DrawArea (холст для рисования):

class DrawArea : public QWidget
{
	Q_OBJECT
	private:

		QList<Curve> *list;
	public:

		DrawArea(QList<Curve> *l, QWidget *parent = 0);
		~DrawArea();

	protected:

		void ddd();
		void paintEvent(QPaintEvent *event);
};

DrawArea::DrawArea(QList<Curve> *l, QWidget *parent) : QWidget(parent) 
{
	list = l;
	ddd();
}

DrawArea::~DrawArea()
{
}

void DrawArea::ddd()
{

	int i;
	Curve cur;
	for(i = 0; i <= 15; i++)
	{
		cur = list->value(i);
		printf("done! %i\n", *(cur.p));
	}
}

void DrawArea::paintEvent(QPaintEvent *)
{
    QPainter board(this);
    ddd(); // тут сегфолт
}

Вот из конструктора можно поуказателю на QList доступится к элементам (ф-ция ddd), а из paintEventa (метод єтого же класса) уже сегфолт!
Список я нигде не очищаю и не удаляю вообще.

Что єто за бред?

Р.S. код сократил до предела.

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

А где вызов конструктора? Подозреваю, что тот QList, что передавался на вход, был удалён.

Кстати, почему бы не передать его по значению, а не по указателю и держать локальную копию?

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

> Кстати, почему бы не передать его по значению, а не по указателю и держать локальную копию?

Потому что содержание меняеся вне класа, а копировать постоянно некошерно...

Вызов конструктора:

Window::Window()
{
	setFixedSize(500, 400);

	Curve cur;
	QList<Curve> list;
	int i;
	for(i = 0; i <= 15; i++) list.append(cur);

	area = new DrawArea(&list, this);
	area->setGeometry(100, 100, 300, 300);

	area->show();
}

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

Хм, а ничего, что при выходе из Window::Window() переменная list перестаёт существовать и указатель, лежащий внутри экземпляра объекта DrawArea указывает чёрти куда? ;)

gaa ★★
()
Ответ на: комментарий от fifajan

у тебя QList<Curve> list; локальный. Как только конструктор Window() завершается, list уничтожается, и DrawArea::list указывает в никуда.

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

> кстати это только что обсуждали в теме про QListView

Самая распространённая ошибка обучающихся плюсопрограммистов.

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

> Хм, а ничего, что при выходе из Window::Window() переменная list перестаёт существовать и указатель, лежащий внутри экземпляра объекта DrawArea указывает чёрти куда? ;)

За очень короткое время порезал код, что б как-то избавится от предыдущей ошибки, бошка закипела и поперло...

Спасибо! Делать лабы в последний день - одно удовольствие :)

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

QList - implicitly shared class. Его нужно использовать по значению, а не по указателю, потому что:

1. Это безопастно из-за отсутствия выделения/удаления в памяти, раздельного доступа к данным.

2. Это быстро: копирование контейнеров - атомарная операция.

3. Это потокобезопастно: контейнеры можно копировать в другой поток без мутексов.

Читать документацию по Implicitly Shared классам в Qt. Коротко: замените все указатели на QList на их значения.

Доступ для чтения из QList нужно делать через QList::at(int index), так как operator[] возвращает не копию, а ссылку на существующий обьект. Это во-первых лишние накладные расходы (читать: тормоза) из-за того что в Implicitly Shared классах реализован метод Copy-On-Write (грубо - лишняя операция проверки количества ссылок на обьект), во-вторых это небезопастно, так как запись типа:

if ( myList[5] = 3 ) ...

не вызовет ошибку компиляции и перезатрёт существующее значение.

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