Russian Qt Forum

Qt => Вопросы новичков => Тема начата: zagruzkaaa от Август 27, 2015, 16:46



Название: Как лучше создавать объекты
Отправлено: zagruzkaaa от Август 27, 2015, 16:46
Создаю различные объекты на форме через код, например кнопки, тексредакторы и т.д. Они будут находится на форме с самого начала и до конца закрытия формы. Так вот: лучше создавать их через указатель, т.е через new или без? И в чем отличие? Спасибо


Название: Re: Как лучше создавать объекты
Отправлено: gil9red от Август 27, 2015, 17:07
Код:
без new объекты создаются на стеке и уничтожаются как только объект выходит из зоны видимости (стек убивается).
зона видимости ограничена фугурными скопками (да поправят меня строгие форумчане), это: функции, классы, циклы и т.п. вы можете просто создать фигурные скопки и туда код писать, не обязательно, чтобы они относились к какому-нибудь оператору / функции.

например, вы создали без new в функции и после того как функция выполнится, то все объекты в ней убиваются

[code=cpp]
void foo() {
    QWidget w;
    w.show();  // w живет и видим пока функция выполняется
}
Поэтому, например, если вы хотите создать функцию, в которой создаются окна, то нужно создавать их с new

А вот диалоги удобно создавать в стеке, потому что, когда вызываете функцию явно exec() или какой-нибудь их метод для их вызова (например, getOpenFileName (http://doc.qt.io/qt-5/qfiledialog.html#getOpenFileName) у qfiledialog), то пока их окна открыты выполнение функции остановлено и уже после закрытия окна дальше пойдет выполнение (для одного потока).
Код
C++ (Qt)
void foo() {
...
   QDialog w;
   w.exec(); // пока диалог открыт, дальше этой строки не выполняется код
...
}

Если вы создаете объекты, которые нужны только при выполнении функции, то создаете без new

это лучше
Код
C++ (Qt)
void foo {
   QString s = "Hello";
   qDebug() << s;
}
 
чем это
Код
C++ (Qt)
void foo {
   QString * s = new QString("Hello");
   qDebug() << s;
   delete s;
}
[/code]


Название: Re: Как лучше создавать объекты
Отправлено: kuzulis от Август 27, 2015, 18:05
А если без new:

Код
C++ (Qt)
 
class Widget : public QWidget
{
...
private:
   QLabel m_label;
   QLineEdit m_lineEdit;
}
 
 

то что? ;)


Название: Re: Как лучше создавать объекты
Отправлено: gil9red от Август 27, 2015, 21:13
А если без new:

Код
C++ (Qt)
 
class Widget : public QWidget
{
...
private:
   QLabel m_label;
   QLineEdit m_lineEdit;
}
 
 

то что? ;)

Было лень и конец рабочего дня, чтобы все варианты описывать :)


Название: Re: Как лучше создавать объекты
Отправлено: zagruzkaaa от Август 27, 2015, 22:37
как раз интересно, в случае описание объектов класса: их лучше создавать через указатель или без


Название: Re: Как лучше создавать объекты
Отправлено: Igors от Август 28, 2015, 08:25
А если без new:

Код
C++ (Qt)
 
class Widget : public QWidget
{
...
private:
   QLabel m_label;
   QLineEdit m_lineEdit;
}
 
 

то что? ;)
Та ничего хорошего. В простом примере выше все будет работать, в более сложных нет, получите двойное удаление

как раз интересно, в случае описание объектов класса: их лучше создавать через указатель или без
Здесь однозначно указатель


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 11:59
Та ничего хорошего. В простом примере выше все будет работать, в более сложных нет, получите двойное удаление
И примен такого случая сможете привести?


Название: Re: Как лучше создавать объекты
Отправлено: Igors от Август 28, 2015, 12:22
Цитата: cpp
class Widget : public QWidget
{
...
private:
    QWidget m_widget;
    QLabel m_label;
}
Пусть m_label должен иметь родителем m_widget. Тогда (при удалении Widget), если первым удалится m_label - все норм, он вычеркнется из чайлдов m_widget. Но если наоборот - тогда m_widget захочет грохнуть m_label, а это не указатель на кучу. Конечно если объявлять "в нужном порядке" - будет работать, но ну его нафиг


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 12:26
Вам придется их описывать/конструировать в нужном порядке, иначе у вас даже не сконструируется.
Поэтому, это рабочий случай. Стандарт гарантирует порядок конструирования/разрушения, а компилятор предупредит о нарушении порядка.


Название: Re: Как лучше создавать объекты
Отправлено: __Heaven__ от Август 28, 2015, 13:32
А что там про выравнивание в памяти? Без указателей вроде же лучше?


Название: Re: Как лучше создавать объекты
Отправлено: Igors от Август 28, 2015, 13:42
..., а компилятор предупредит о нарушении порядка.
???
Код
C++ (Qt)
class CBad : public QWidget {
public:
CBad( void ) : m_lab("Lab", &m_widget)
{
}
 
public:
QLabel m_lab;
QWidget m_widget;
};
 
Не вижу даже варнинга  :)

А что там про выравнивание в памяти? Без указателей вроде же лучше?
Адрес структур/классов выравнивается одинаково, не зависит от того где распределяется структура. "Парент удаляет чайлда" - а значит парент предполагает что чайлд в куче. Пытаться это как-то обходить не очень разумно, да и не видно зачем


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 14:50
Не вижу даже варнинга  :)
А программа работает?
Поэтому я и написал, что вам придется соблюдать порядок конструирования, иначе до двойного освобождения дело даже не дойдет.


Название: Re: Как лучше создавать объекты
Отправлено: Пантер от Август 28, 2015, 15:05
Не вижу даже варнинга  :)
А программа работает?
Поэтому я и написал, что вам придется соблюдать порядок конструирования, иначе до двойного освобождения дело даже не дойдет.

А почему бы ей не работать? Он же ссылку берет, а она рабочая. Вот если бы он значение брал, то получил бы лажу.

Код
C++ (Qt)
struct A
{
int a;
int b;
A() : a(b), b(10) {std::cout << a << " " << b << std::endl;}
};
...........
./a.out
0 10
[/code!


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 15:14
А почему бы ей не работать? Он же ссылку берет, а она рабочая. Вот если бы он значение брал, то получил бы лажу.
Не важно по ссылке или по значению. Объект label, получив ссылку, воспользуется методами  объекта widget, а он еще не сконструирован.
Поэтому, придется widget декларировать и конструировать первым, а если попробуете конструировать в другом порядке чем декларировали - получите предупреждение.


Название: Re: Как лучше создавать объекты
Отправлено: Igors от Август 28, 2015, 15:20
А почему бы ей не работать? Он же ссылку берет, а она рабочая. Вот если бы он значение брал, то получил бы лажу.
В данном случае она берет адрес члена, это само по себе корректно, но вызывается метод этого члена, а он-то еще не сконструирован - вылет. Ну и в конце-концов  можно было и так
Код:
class CBad2 : public QWidget {
public:
CBad2( void ) : m_lab("Lab")
{
          m_lab.setParent(&m_widget);
}
 
public:
QLabel m_lab;
QWidget m_widget;
};
Тоже полетит но не сразу. Поэтому всю затею "члены вместо указателей" надо признать совершенно никчемной, тем паче в разделе для новичков


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 15:23
Ну не надо юлить про темы для новичков. :)
Про целесообразность такого описания никто не спорил. Просто вы в очередной раз придумали про невозможность такого описания в связи с двойным освобождением памяти, а я вас поправил.
Так писать можно и вы будете вынужденны соблюдать правильный порядок инициализации, иначе до двойного освобождения дело даже не дойдет.


Название: Re: Как лучше создавать объекты
Отправлено: Igors от Август 28, 2015, 16:01
Про целесообразность такого описания никто не спорил.
Да какая "целесообразность", это слово здесь совершенно неуместно, объявляя виджеты-члены мы просто роем себе яму пытаясь пысать против "Qt ветра"

Так писать можно и...
А это называется "вводить в заблуждение", причем исполняется сознательно


Название: Re: Как лучше создавать объекты
Отправлено: Old от Август 28, 2015, 16:07
А это называется "вводить в заблуждение", причем исполняется сознательно
Вовсе нет, все будет работать как надо.
Хотите опровергнуть, приведите компилируемый проект, в котором все будет создаваться и работать, а при разрушении будет двойное освобождение памяти.