Russian Qt Forum

Qt => Общие вопросы => Тема начата: Yan от Январь 28, 2007, 21:34



Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: Yan от Январь 28, 2007, 21:34
Создаю QList:
mainwindow.h:
Код:

..
public:
QList<CScreenShot> screenShots;
...


Класс CScreenShot кроме конструктора и деструктора ничего не содержит:
screenshot.h:
Код:

...
class CScreenShot{
public:
CScreenShot();
~CScreenShot();
};
...

screenshot.cpp:
Код:

CScreenShot::CScreenShot()
{
QMessageBox::about(NULL, "About","constructor");
}
CScreenShot::~CScreenShot(){
QMessageBox::about(NULL, "About","destructor");
}


Добаляю новый элемент в QList так:
mainwindow.cpp:
Код:

...
screenShots.append(CScreenShot());
...


При добавлении зачем-то помимо конструктора CScreenShot(), вызывается ещё и деструктор ~CScreenShot().
Зачем?
Где я ошибся?

добавлено спустя 4 минуты:

  P.S.  QT 4.1.0 под Windows


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: alex12 от Январь 28, 2007, 22:36
Код:

...
screenShots.append(CScreenShot());
...


Здесь сначала создается анонимный экземпляр класса, а потом при помощи конструктора копий создается новый экземпляр. Именно этот новый экземпляр помещается в контейнер. После этого анонимный объект уничтожается деструктором (что мы и видим). Создание второго экземпляра не отслеживается т.к. он делается конструктором копий, а не конструктором по умолчанию.

По-моему это работает именно так.


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: Yan от Январь 28, 2007, 23:22
Хорошо, тогда как мне отследить этот момент, и сделать так, чтобы код в деструкторе выполнялся только при удалении элемента из QList, например:
Код:
screenShots.removeFirst();


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: alex12 от Январь 28, 2007, 23:54
Вот здесь и начинается C++ :D

Контейнеры Qt хранят данные по значению, но сами Qt типы с данными при этом используют метод хранения copy-on-write. Поэтому можно спокойно копировать любые QByteArray или QImage без размножения самих данных и потери скорости.

В случае запихивания класса в контейнер без его копирования не обойтись. Отследить же реальное его уничтожение можно, думаю, при помощи подсчета ссылок. Для этого нужно переопределить конструктор копий и при создании копии увеличивать счетчик, а в деструкторе его уменьшать. Это одна из стандартных идиом C++.

Все это относительно сложно и нельзя ли обойтись без этого?


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: Yan от Январь 29, 2007, 03:30
Да, пожалуй, обойдусь более простым решением.
Спасибо.


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: Dendy от Январь 29, 2007, 08:38
Более простое решение - поместить данньІе класса CScreenShot в обёртку с подсчётом ссьІлок, что будет заниматься их вьІделением и унитожением. Кроме того в Qt предусмотрен механизм атомарного копирования между потоками таких данньІх.

Код:
class CScreenShotData : public QSharedData
{
public:
  CScreenShotData()
  {
    // real constructor
  }

  ~CScreenShotData()
  {
    // real destructor
  }
};


class CScreenShot
{
public:
  CScreenShot();

private:
  QSharedDataPointer<CScreenShotData> d;
};


Теперь деструктор будет вьІзьІваться только при уничтожении последнего обьекта, что ссьІлается на данньІе.


Название: При добавлении в QList вызывается деструтор. Зачем?
Отправлено: alex12 от Январь 29, 2007, 11:58
Теперь буду знать как не изобретать велосипед. :D