Russian Qt Forum

Qt => Вопросы новичков => Тема начата: vorotislav от Сентябрь 02, 2015, 14:12



Название: smart pointer in Qt
Отправлено: vorotislav от Сентябрь 02, 2015, 14:12
Доброго времени суток.

Прочитал про умные указатели, захотел их освоить.
Начал в проекте пробовать перевести указатели на shared_ptr и unique_ptr
в pro-файле:
CONFIG += c++14
QMAKE_CXXFLAGS += -std=c++11

включил заголовочный файл <memory>
Код:
    std::unique_ptr<DialogInfoUser> dialog (new DialogInfoUser (this));
    dialog. ??? тут нет метода exec()

Пробовал заменить на shared_ptr - тоже самое.
Как мне вызвать метод? Что я делаю не так?
Пробовал в pro файле писать
CONFIG += c++11
QMAKE_CXXFLAGS += -std=c++0х
результат тот же.
P.S.
Qt 5.5, MinGw 4.9.2, Win7.
P.P.S
Возможно в проектах на Qt не следует пользоваться std::shared_ptr, а взяться за QSharedPointer?
Но при беглом прочтении про QSharedPointer, а так же при попытке обернуть указатель, то я так же не могу сразу достучаться до методов, только через .data()

если использовать shared:
Код:
    std::shared_ptr<DialogInfoUser> dialog (new DialogInfoUser (this));
    dialog.get()->exec(); //

То вот таким способом метод доступен. Но является ли это правильным использованием? И почему в таком случае через get() не доступен при unique_ptr?


Название: Re: smart pointer in Qt
Отправлено: Igors от Сентябрь 02, 2015, 14:49
Писать просто dialog->exec(); (во всех случаях). Ну или др метод вместо exec

Возможно в проектах на Qt не следует пользоваться std::shared_ptr, а взяться за QSharedPointer?
Для начала присмотритесь к QPointer, очень полезная вещь, пусть не смущает что работает только для QObject. Здесь важно что QPointer понимается модулями Qt, а вот др "шары" нет. Пример
Код
C++ (Qt)
{
QPointer <QLabel> lab1(new QLabel("Lab1", parent));  
QSharedPointer <QLabel> lab2(new QLabel("Lab2", parent));   // или std::shared_ptr
.... // чего-то делаем
if (!lab1.isNull()) lab1->setText("End");
if (!lab2.isNull()) lab2->setText("End");
}  // здесь оба lab1 и lab2 будут удалены (если еще не были)
 
QPointer отработает железно, а вот QSharedPointer хз. Если напр был удален сам parent - он вызовет удаление указателя сидящего в lab2, а это разрушит QSharedPointer.

В общем, не слишком рвитесь вперед  :) 


Название: Re: smart pointer in Qt
Отправлено: Tuxford от Сентябрь 02, 2015, 15:00
Возможно в проектах на Qt не следует пользоваться std::shared_ptr, а взяться за QSharedPointer?
Но при беглом прочтении про QSharedPointer, а так же при попытке обернуть указатель, то я так же не могу сразу достучаться до методов, только через аким
От части да. Это касается всякой гуйни. Сама архитектура Qt такая интересная. Когда занимался написание UI, то вообще старался не делать никаких динамических выделений. Кора была написана без Qt. Очень не хотелось влазить в этот Qtшных хлам.


Название: Re: smart pointer in Qt
Отправлено: KrupaKarlo от Сентябрь 02, 2015, 15:42
Код:
 std::unique_ptr<DialogInfoUser> dialog (new DialogInfoUser (this));

Данный код уже не верен. Смысл smart pointer в том, чтобы не управлять вручную временем жизни объекта.  А тут
Код:
new DialogInfoUser (this)
вы говорите, что родитель управляет временем жизни объекта. получается один раз ваш объект попытается уничтожить родитель, а второй раз std::unique_ptr.

В обычной ситуации не надо использовать get() или data(). Они нужны, когда требуется голый указатель но объект(к примеру для создания коннекта сигнала). Обычно просто пишите  dialog->exec(); //


Название: Re: smart pointer in Qt
Отправлено: Авварон от Сентябрь 02, 2015, 16:47
Данный код уже не верен. Смысл smart pointer в том, чтобы не управлять вручную временем жизни объекта.  А тут
Код:
new DialogInfoUser (this)
вы говорите, что родитель управляет временем жизни объекта. получается один раз ваш объект попытается уничтожить родитель, а второй раз std::unique_ptr.

Это не всегда неверно. Например, если объект создается в ф-ии, из к-ой он возвращается по рав птру/юнику, но к-ая может тровнуть. В случае трова логично удалить объект - заворачиваем в юник/скопед поинтер.
Более конктерный пример - QDialog *createDialog(QWidget *parent = nullptr)


Название: Re: smart pointer in Qt
Отправлено: KrupaKarlo от Сентябрь 02, 2015, 18:43
тут приведен конкретный пример, когда это неверно. Надо четко понимать кто и что у вас удаляет.


Название: Re: smart pointer in Qt
Отправлено: vorotislav от Сентябрь 02, 2015, 21:35
KrupaKarlo, ок, я согласен с тем, что за удалением объекта следит родитель. Но если предположим, программа 24/7, она не выключается. Главное окно не выключается, значит и этот объект не удаляется? А если это окно настроек, и раз в день его открывают? Так и будет выделяться память и не освобождаться, или я чего то не понимаю?

Касаемо темы и моего главного вопроса, оказывается все просто. А не один раз видел ответ, и здесь он сразу был все дело в dialog->exec(); но я слишком быстро привык, что creator умеет менять "." на "->" когда это надо. Поэтому писал всегда "dialog." а дальше он сам. В случае с умным указателем такого не происходило, автозамены не было, не было метода exec. Я думал что все не работает. Всем большое спасибо.


Название: Re: smart pointer in Qt
Отправлено: Old от Сентябрь 02, 2015, 21:42
Так и будет выделяться память и не освобождаться, или я чего то не понимаю?
Именно так и будет, память разом освоболится только при завершении программы (при разрушении главного окна). Это 100% утечка памяти.


Название: Re: smart pointer in Qt
Отправлено: KrupaKarlo от Сентябрь 03, 2015, 09:39
Ненадо просто временные объекты делать через new без надобности.

К примеру если вам нужен диалог не надо его создавать в конструкторе и хранить пока программа не сдохнет. делайте так
Код:
void func(){
     MyDialog dlg;
     if(dlg.exec() == "что вас интересует")
     {
        //TODO
     }
}
В такому случае ваш диалог уничтожится сам по окончании функции


Название: Re: smart pointer in Qt
Отправлено: Авварон от Сентябрь 03, 2015, 12:14
KrupaKarlo
Я уже приводил пример.

Код:
QMenu *Widget::createDefaultMenu()
{
    QScopedPointer<QMenu> menu(new QMenu);
    menu->addAction(tr("Cool action")); // can throw
    return menu.take();
}

void Window::contextMenuEvent(QContextMenuEvent *event)
{
    QScopedPointer<QMenu> menu(widget->createDefaultMenu());
    menu->addAction(tr("Even cooler action")); // can throw
    menu->exec(event->pos());
}



Название: Re: smart pointer in Qt
Отправлено: Igors от Сентябрь 03, 2015, 12:29
Код:
    menu->addAction(tr("Cool action")); // can throw
Ага, оказывается "тровнуть" - это throw  :) Но пример неудачен. Слабо верится что addAction может выбросить исключение, а если это уж произойдет то не видно что должен с ним делать обработчик "наверху", поэтому try/catch должен быть здесь же


Название: Re: smart pointer in Qt
Отправлено: KrupaKarlo от Сентябрь 03, 2015, 14:51
KrupaKarlo
Я уже приводил пример.

Код:
QMenu *Widget::createDefaultMenu()
{
    QScopedPointer<QMenu> menu(new QMenu);
    menu->addAction(tr("Cool action")); // can throw
    return menu.take();
}

void Window::contextMenuEvent(QContextMenuEvent *event)
{
    QScopedPointer<QMenu> menu(widget->createDefaultMenu());
    menu->addAction(tr("Even cooler action")); // can throw
    menu->exec(event->pos());
}



Вы создаете меню зачем то через new оборачиваете все это в smart pointer. Если вам кажется что это тоже самое что на стеке создать объект и он сам сдохнет то ок



Название: Re: smart pointer in Qt
Отправлено: Авварон от Сентябрь 04, 2015, 10:29
Вы создаете меню зачем то через new оборачиваете все это в smart pointer. Если вам кажется что это тоже самое что на стеке создать объект и он сам сдохнет то ок

Facepalm. Может быть, для того, чтобы вернуть из функции? Если вы не заметили, Widget и Window - разные классы. Как я на стеке в Window создам меню из Widget?